This source file includes following definitions.
- it_char_has_category
- char_can_wrap_before
- char_can_wrap_after
- fill_column_indicator_column
- redisplay_other_windows
- wset_redisplay
- fset_redisplay
- bset_redisplay
- bset_update_mode_line
- wset_update_mode_line
- ATTRIBUTE_FORMAT_PRINTF
- ATTRIBUTE_FORMAT_PRINTF
- window_text_bottom_y
- window_box_width
- window_box_height
- window_box_left_offset
- window_box_right_offset
- window_box_left
- window_box_right
- window_box
- window_box_edges
- line_bottom_y
- DEFUN
- default_line_pixel_height
- string_from_display_spec
- window_hscroll_limited
- reset_box_start_end_flags
- pos_visible_p
- check_char_and_length
- string_pos_nchars_ahead
- string_pos
- c_string_pos
- number_of_chars
- compute_string_pos
- estimate_mode_line_height
- pixel_to_glyph_coords
- x_y_to_hpos_vpos
- frame_to_window_pixel_xy
- get_glyph_string_clip_rects
- get_glyph_string_clip_rect
- get_phys_cursor_geometry
- remember_mouse_glyph
- adjust_window_ends
- hscrolling_current_line_p
- safe_eval_handler
- safe__call
- safe_call
- safe_call1
- safe__call1
- safe_eval
- safe__eval
- safe_call2
- CHECK_IT
- CHECK_WINDOW_END
- init_iterator
- get_narrowed_width
- get_narrowed_len
- get_medium_narrowing_begv
- get_medium_narrowing_zv
- get_nearby_bol_pos
- get_small_narrowing_begv
- get_large_narrowing_begv
- get_large_narrowing_zv
- unwind_narrowed_begv
- start_display
- in_ellipses_for_invisible_text_p
- init_from_display_pos
- init_to_row_start
- init_to_row_end
- handle_stop
- compute_stop_pos
- compute_display_string_pos
- compute_display_string_end
- handle_fontified_prop
- face_at_pos
- handle_face_prop
- underlying_face_id
- face_before_or_after_it_pos
- handle_invisible_prop
- setup_for_ellipsis
- find_display_property
- get_display_property
- display_min_width
- handle_display_prop
- handle_display_spec
- display_prop_end
- handle_single_display_spec
- display_prop_intangible_p
- single_display_spec_string_p
- display_prop_string_p
- string_buffer_position_lim
- string_buffer_position
- handle_composition_prop
- handle_overlay_change
- next_overlay_string
- compare_overlay_entries
- load_overlay_strings
- get_overlay_strings_1
- get_overlay_strings
- push_it
- iterate_out_of_display_property
- restore_face_box_flags
- pop_it
- back_to_previous_line_start
- strings_with_newlines
- forward_to_next_line_start
- back_to_previous_visible_line_start
- reseat_at_previous_visible_line_start
- reseat_at_next_visible_line_start
- reseat
- reseat_1
- reseat_to_string
- lookup_glyphless_char_display
- merge_escape_glyph_face
- merge_glyphless_glyph_face
- forget_escape_and_glyphless_faces
- get_next_display_element
- set_iterator_to_next
- next_element_from_display_vector
- get_visually_first_element
- next_element_from_string
- next_element_from_c_string
- next_element_from_ellipsis
- next_element_from_image
- next_element_from_xwidget
- next_element_from_stretch
- compute_stop_pos_backwards
- handle_stop_backwards
- next_element_from_buffer
- next_element_from_composition
- move_it_in_display_line_to
- move_it_in_display_line
- move_it_to
- move_it_vertically_backward
- move_it_vertically
- move_it_past_eol
- move_it_by_lines
- partial_line_height
- fast_move_it_horizontally
- in_display_vector_p
- window_text_pixel_size
- DEFUN
- format_nargs
- add_to_log
- vadd_to_log
- message_log_maybe_newline
- message_dolog
- message_log_check_duplicate
- message3
- message_to_stderr
- message3_nolog
- message1
- message1_nolog
- message_with_string
- ATTRIBUTE_FORMAT_PRINTF
- message
- update_echo_area
- ensure_echo_area_buffers
- with_echo_area_buffer
- with_echo_area_buffer_unwind_data
- unwind_with_echo_area_buffer
- setup_echo_area_for_printing
- display_echo_area
- display_echo_area_1
- resize_echo_area_exactly
- resize_mini_window_1
- resize_mini_window
- current_message
- current_message_1
- push_message
- restore_message
- pop_message_unwind
- check_message_stack
- clear_message_stack
- truncate_echo_area
- truncate_message_1
- set_message
- set_message_1
- clear_message
- clear_garbaged_frames
- echo_area_display
- window_buffer_changed
- mode_line_update_needed
- window_frozen_p
- format_mode_line_unwind_data
- unwind_format_mode_line
- store_mode_line_noprop_char
- store_mode_line_noprop
- gui_consider_frame_title
- needs_no_redisplay
- prepare_menu_bars
- update_menu_bar
- restore_selected_window
- restore_frame_selected_window
- update_tab_bar
- display_tab_bar
- build_desired_tab_bar_string
- display_tab_bar_line
- tab_bar_height
- redisplay_tab_bar
- tab_bar_item_info
- get_tab_bar_item
- get_tab_bar_item_kbd
- handle_tab_bar_click
- note_tab_bar_highlight
- tty_get_tab_bar_item
- tty_handle_tab_bar_click
- update_tool_bar
- build_desired_tool_bar_string
- display_tool_bar_line
- tool_bar_height
- redisplay_tool_bar
- tool_bar_item_info
- get_tool_bar_item
- handle_tool_bar_click_with_device
- handle_tool_bar_click
- note_tool_bar_highlight
- hscroll_window_tree
- hscroll_windows
- debug_method_add
- text_outside_line_unchanged_p
- redisplay
- overlay_arrow_string_or_property
- overlay_arrow_in_current_buffer_p
- overlay_arrows_changed_p
- update_overlay_arrows
- overlay_arrow_at_row
- check_point_in_composition
- reconsider_clip_changes
- propagate_buffer_redisplay
- redisplay_internal
- unwind_redisplay_preserve_echo_area
- redisplay_preserve_echo_area
- unwind_redisplay
- unwind_display_working_on_window
- mark_window_display_accurate_1
- mark_window_display_accurate
- disp_char_vector
- block_buffer_flips
- unblock_buffer_flips
- buffer_flipping_blocked_p
- redisplay_windows
- redisplay_window_error
- redisplay_window_0
- redisplay_window_1
- update_redisplay_ticks
- set_cursor_from_row
- run_window_scroll_functions
- cursor_row_fully_visible_p
- try_scrolling
- compute_window_start_on_continuation_line
- try_cursor_movement
- set_vertical_scroll_bar
- set_horizontal_scroll_bar
- window_start_acceptable_p
- DEFUN
- redisplay_window
- try_window
- try_window_reusing_current_matrix
- find_last_row_displaying_text
- find_last_unchanged_at_beg_row
- find_first_unchanged_at_end_row
- sync_frame_with_window_matrix_rows
- row_containing_pos
- try_window_id
- dump_glyph_row
- dump_glyph
- dump_glyph_row
- DEFUN
- DEFUN
- DEFUN
- get_overlay_arrow_glyph_row
- insert_left_trunc_glyphs
- row_hash
- compute_line_metrics
- clear_position
- append_space_for_newline
- extend_face_to_end_of_line
- trailing_whitespace_p
- highlight_trailing_whitespace
- row_for_charpos_p
- cursor_row_p
- push_prefix_prop
- get_it_property
- get_line_prefix_it_property
- handle_line_prefix
- unproduce_glyphs
- find_row_edges
- display_count_lines_logically
- display_count_lines_visually
- maybe_produce_line_number
- should_produce_line_number
- row_text_area_empty
- display_line
- DEFUN
- DEFUN
- DEFUN
- display_menu_bar
- deep_copy_glyph_row
- display_tty_menu_item
- redisplay_mode_lines
- display_mode_lines
- display_mode_line
- move_elt_to_front
- safe_set_text_properties
- display_mode_element
- store_mode_line_string
- pint2str
- pint2hrstr
- decode_mode_spec_coding
- percent99
- decode_mode_spec
- count_lines
- display_count_lines
- display_string
- invisible_prop
- DEFUN
- calc_pixel_width_or_height
- get_font_ascent_descent
- dump_glyph_string
- init_glyph_string
- append_glyph_string_lists
- prepend_glyph_string_lists
- append_glyph_string
- get_char_face_and_encoding
- get_glyph_face_and_encoding
- get_char_glyph_code
- fill_composite_glyph_string
- fill_gstring_glyph_string
- fill_glyphless_glyph_string
- fill_glyph_string
- fill_image_glyph_string
- fill_xwidget_glyph_string
- fill_stretch_glyph_string
- get_per_char_metric
- normal_char_ascent_descent
- normal_char_height
- gui_get_glyph_overhangs
- left_overwritten
- left_overwriting
- right_overwritten
- right_overwriting
- set_glyph_string_background_width
- glyph_string_containing_background_width
- compute_overhangs_and_x
- draw_glyphs
- font_for_underline_metrics
- append_glyph
- append_composite_glyph
- take_vertical_position_into_account
- produce_image_glyph
- produce_xwidget_glyph
- append_stretch_glyph
- produce_stretch_glyph
- produce_special_glyphs
- pad_mode_line
- calc_line_height_property
- append_glyphless_glyph
- produce_glyphless_glyph
- gui_produce_glyphs
- gui_write_glyphs
- gui_insert_glyphs
- gui_clear_end_of_line
- get_specified_cursor_type
- set_frame_cursor_types
- get_window_cursor_type
- notice_overwritten_cursor
- gui_fix_overlapping_area
- draw_phys_cursor_glyph
- erase_phys_cursor
- display_and_set_cursor
- update_window_cursor
- update_cursor_in_window_tree
- gui_update_cursor
- gui_clear_cursor
- draw_row_with_mouse_face
- show_mouse_face
- clear_mouse_face
- coords_in_mouse_face_p
- cursor_in_mouse_face_p
- rows_from_pos_range
- mouse_face_from_buffer_pos
- fast_find_string_pos
- mouse_face_from_string_pos
- on_hot_spot_p
- find_hot_spot
- define_frame_cursor1
- note_mode_line_or_margin_highlight
- note_mouse_highlight
- gui_clear_window_mouse_face
- cancel_mouse_face
- expose_area
- expose_line
- expose_overlaps
- phys_cursor_in_rect_p
- gui_draw_vertical_border
- gui_draw_right_divider
- gui_draw_bottom_divider
- expose_window
- expose_window_tree
- expose_frame
- gui_intersect_rectangles
- gui_union_rectangles
- syms_of_xdisp
- init_xdisp
- show_hourglass
- start_hourglass
- cancel_hourglass
- adjust_glyph_width_for_mouse_face
- get_cursor_offset_for_mouse_face
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433 #include <config.h>
434 #include <stdlib.h>
435 #include <limits.h>
436 #include <math.h>
437
438 #include "lisp.h"
439 #include "atimer.h"
440 #include "composite.h"
441 #include "keyboard.h"
442 #include "sysstdio.h"
443 #include "systime.h"
444 #include "frame.h"
445 #include "window.h"
446 #include "termchar.h"
447 #include "dispextern.h"
448 #include "character.h"
449 #include "category.h"
450 #include "buffer.h"
451 #include "charset.h"
452 #include "indent.h"
453 #include "commands.h"
454 #include "keymap.h"
455 #include "disptab.h"
456 #include "termhooks.h"
457 #include "termopts.h"
458 #include "intervals.h"
459 #include "coding.h"
460 #include "region-cache.h"
461 #include "font.h"
462 #include "fontset.h"
463 #include "blockinput.h"
464 #include "xwidget.h"
465 #ifdef HAVE_WINDOW_SYSTEM
466 #include TERM_HEADER
467 #endif
468
469 #ifndef FRAME_OUTPUT_DATA
470 #define FRAME_OUTPUT_DATA(f) (NULL)
471 #endif
472
473 #define DISP_INFINITY 10000000
474
475
476 static Lisp_Object list_of_error;
477
478 #ifdef HAVE_WINDOW_SYSTEM
479
480
481
482
483 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \
484 (!NILP (Voverflow_newline_into_fringe) \
485 && FRAME_WINDOW_P ((IT)->f) \
486 && ((IT)->bidi_it.paragraph_dir == R2L \
487 ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
488 : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
489 && (IT)->current_x == (IT)->last_visible_x)
490
491 #else
492 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) false
493 #endif
494
495
496
497
498
499 #define IT_DISPLAYING_WHITESPACE(it) \
500 ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
501 || ((STRINGP (it->string) \
502 && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
503 || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
504 || (it->s \
505 && (it->s[IT_BYTEPOS (*it)] == ' ' \
506 || it->s[IT_BYTEPOS (*it)] == '\t')) \
507 || (IT_BYTEPOS (*it) < ZV_BYTE \
508 && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
509 || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))
510
511
512
513 #define NOT_AT_EOL '<'
514 #define NOT_AT_BOL '>'
515 #define LINE_BREAKABLE '|'
516
517 static bool
518 it_char_has_category(struct it *it, int cat)
519 {
520 int ch = 0;
521 if (it->what == IT_CHARACTER)
522 ch = it->c;
523 else if (STRINGP (it->string))
524 ch = SREF (it->string, IT_STRING_BYTEPOS (*it));
525 else if (it->s)
526 ch = it->s[IT_BYTEPOS (*it)];
527 else if (IT_BYTEPOS (*it) < ZV_BYTE)
528 ch = *BYTE_POS_ADDR (IT_BYTEPOS (*it));
529
530 if (ch == 0)
531 return false;
532 else
533 return CHAR_HAS_CATEGORY (ch, cat);
534 }
535
536
537 static bool
538 char_can_wrap_before (struct it *it)
539 {
540 if (!word_wrap_by_category)
541 return !IT_DISPLAYING_WHITESPACE (it);
542
543
544
545
546 int not_at_bol;
547 if (it->glyph_row && it->glyph_row->reversed_p)
548 not_at_bol = NOT_AT_EOL;
549 else
550 not_at_bol = NOT_AT_BOL;
551
552
553 return (!IT_DISPLAYING_WHITESPACE (it)
554
555 && !it_char_has_category (it, not_at_bol));
556 }
557
558
559 static bool
560 char_can_wrap_after (struct it *it)
561 {
562 if (!word_wrap_by_category)
563 return IT_DISPLAYING_WHITESPACE (it);
564
565
566
567
568 int not_at_eol;
569 if (it->glyph_row && it->glyph_row->reversed_p)
570 not_at_eol = NOT_AT_BOL;
571 else
572 not_at_eol = NOT_AT_EOL;
573
574 return (IT_DISPLAYING_WHITESPACE (it)
575
576 || (it_char_has_category (it, LINE_BREAKABLE)
577 && !it_char_has_category (it, not_at_eol)));
578 }
579
580 #undef IT_DISPLAYING_WHITESPACE
581 #undef NOT_AT_EOL
582 #undef NOT_AT_BOL
583 #undef LINE_BREAKABLE
584
585
586
587
588 static int
589 fill_column_indicator_column (struct it *it, int char_width)
590 {
591 if (display_fill_column_indicator
592 && !it->w->pseudo_window_p
593 && it->continuation_lines_width == 0
594 && CHARACTERP (Vdisplay_fill_column_indicator_character))
595 {
596 Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
597 ? BVAR (current_buffer, fill_column)
598 : Vdisplay_fill_column_indicator_column);
599
600
601
602 if (RANGED_FIXNUMP (0, col, INT_MAX))
603 {
604 int icol = XFIXNUM (col);
605 if (!ckd_mul (&icol, icol, char_width)
606 && !ckd_add (&icol, icol, it->lnum_pixel_width))
607 return icol;
608 }
609 }
610 return -1;
611 }
612
613
614
615 bool noninteractive_need_newline;
616
617
618
619 static bool message_log_need_newline;
620
621
622
623
624 static Lisp_Object message_dolog_marker1;
625 static Lisp_Object message_dolog_marker2;
626 static Lisp_Object message_dolog_marker3;
627
628
629
630
631
632
633 static struct text_pos this_line_start_pos;
634
635
636
637
638 static struct text_pos this_line_end_pos;
639
640
641
642 static int this_line_vpos;
643 static int this_line_y;
644 static int this_line_pixel_height;
645
646
647
648
649 static int this_line_start_x;
650
651
652
653
654
655 static struct text_pos this_line_min_pos;
656
657
658
659 static struct buffer *this_line_buffer;
660
661
662
663 static bool overlay_arrow_seen;
664
665
666
667 static Lisp_Object default_invis_vector[3];
668
669
670
671
672
673 Lisp_Object echo_area_window;
674
675
676
677
678 static Lisp_Object Vmessage_stack;
679
680
681
682
683 static bool message_enable_multibyte;
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715 int windows_or_buffers_changed;
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736 int update_mode_lines;
737
738
739
740
741 static bool line_number_displayed;
742
743
744
745
746 Lisp_Object echo_area_buffer[2];
747
748
749
750 static Lisp_Object echo_buffer[2];
751
752
753
754 static Lisp_Object Vwith_echo_area_save_vector;
755
756
757
758
759 static bool display_last_displayed_message_p;
760
761
762
763
764 static bool message_buf_print;
765
766
767
768
769 static bool message_cleared_p;
770
771
772
773
774 #define MAX_SCRATCH_GLYPHS 100
775 static struct glyph_row scratch_glyph_row;
776 static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
777
778
779
780 static int last_height;
781
782
783
784 bool help_echo_showing_p;
785
786
787
788
789
790
791
792 #define TEXT_PROP_DISTANCE_LIMIT 100
793
794
795
796
797
798
799
800
801 #define SAVE_IT(ITCOPY, ITORIG, CACHE) \
802 do { \
803 if (CACHE) \
804 bidi_unshelve_cache (CACHE, true); \
805 ITCOPY = ITORIG; \
806 CACHE = bidi_shelve_cache (); \
807 } while (false)
808
809 #define RESTORE_IT(pITORIG, pITCOPY, CACHE) \
810 do { \
811 if (pITORIG != pITCOPY) \
812 *(pITORIG) = *(pITCOPY); \
813 bidi_unshelve_cache (CACHE, false); \
814 CACHE = NULL; \
815 } while (false)
816
817
818 enum { REDISPLAY_SOME = 2};
819
820 static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
821 struct font *, bool, int *);
822
823 void
824 redisplay_other_windows (void)
825 {
826 if (!windows_or_buffers_changed)
827 windows_or_buffers_changed = REDISPLAY_SOME;
828 }
829
830 void
831 wset_redisplay (struct window *w)
832 {
833
834 if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
835 redisplay_other_windows ();
836 w->redisplay = true;
837 }
838
839 void
840 fset_redisplay (struct frame *f)
841 {
842 redisplay_other_windows ();
843 f->redisplay = true;
844 }
845
846 void
847 bset_redisplay (struct buffer *b)
848 {
849 int count = buffer_window_count (b);
850 if (count > 0)
851 {
852
853 if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
854 redisplay_other_windows ();
855
856
857
858 b->text->redisplay = true;
859 }
860 }
861
862 void
863 bset_update_mode_line (struct buffer *b)
864 {
865 if (!update_mode_lines)
866 update_mode_lines = REDISPLAY_SOME;
867 b->text->redisplay = true;
868 }
869
870 void
871 wset_update_mode_line (struct window *w)
872 {
873 w->update_mode_line = true;
874
875
876
877
878
879
880 wset_redisplay (w);
881 }
882
883 DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
884 Sset_buffer_redisplay, 4, 4, 0,
885 doc:
886 )
887 (Lisp_Object symbol, Lisp_Object newval, Lisp_Object op, Lisp_Object where)
888 {
889 bset_update_mode_line (current_buffer);
890 current_buffer->prevent_redisplay_optimizations_p = true;
891 return Qnil;
892 }
893
894
895
896
897
898 #ifdef GLYPH_DEBUG
899 extern bool trace_redisplay_p EXTERNALLY_VISIBLE;
900 bool trace_redisplay_p;
901 #else
902 enum { trace_redisplay_p = false };
903 #endif
904 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
905 redisplay_trace (char const *fmt, ...)
906 {
907 if (trace_redisplay_p)
908 {
909 va_list ap;
910 va_start (ap, fmt);
911 vprintf (fmt, ap);
912 va_end (ap);
913 }
914 }
915
916 #ifdef DEBUG_TRACE_MOVE
917 extern bool trace_move EXTERNALLY_VISIBLE;
918 bool trace_move;
919 #else
920 enum { trace_move = false };
921 #endif
922 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
923 move_trace (char const *fmt, ...)
924 {
925 if (trace_move)
926 {
927 va_list ap;
928 va_start (ap, fmt);
929 vprintf (fmt, ap);
930 va_end (ap);
931 }
932 }
933
934
935
936 static struct buffer *displayed_buffer;
937
938
939
940 enum prop_handled
941 {
942 HANDLED_NORMALLY,
943 HANDLED_RECOMPUTE_PROPS,
944 HANDLED_OVERLAY_STRING_CONSUMED,
945 HANDLED_RETURN
946 };
947
948
949
950
951 struct props
952 {
953
954 short name;
955
956
957 enum prop_idx idx;
958
959
960
961 enum prop_handled (*handler) (struct it *it);
962 };
963
964 static enum prop_handled handle_face_prop (struct it *);
965 static enum prop_handled handle_invisible_prop (struct it *);
966 static enum prop_handled handle_display_prop (struct it *);
967 static enum prop_handled handle_composition_prop (struct it *);
968 static enum prop_handled handle_overlay_change (struct it *);
969 static enum prop_handled handle_fontified_prop (struct it *);
970
971
972
973 static struct props it_props[] =
974 {
975 {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
976
977
978 {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
979 {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
980 {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
981 {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
982 {0, 0, NULL}
983 };
984
985
986
987 enum move_it_result
988 {
989
990 MOVE_UNDEFINED,
991
992
993 MOVE_POS_MATCH_OR_ZV,
994
995
996 MOVE_X_REACHED,
997
998
999
1000 MOVE_LINE_CONTINUED,
1001
1002
1003
1004 MOVE_LINE_TRUNCATED,
1005
1006
1007 MOVE_NEWLINE_OR_CR
1008 };
1009
1010
1011
1012
1013
1014
1015 #define CLEAR_FACE_CACHE_COUNT 500
1016 static int clear_face_cache_count;
1017
1018
1019
1020 #ifdef HAVE_WINDOW_SYSTEM
1021 #define CLEAR_IMAGE_CACHE_COUNT 101
1022 static int clear_image_cache_count;
1023
1024
1025 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
1026 #endif
1027
1028
1029
1030 bool redisplaying_p;
1031
1032
1033
1034
1035
1036
1037
1038
1039 bool display_working_on_window_p;
1040
1041
1042
1043
1044 Lisp_Object help_echo_string;
1045 Lisp_Object help_echo_window;
1046 Lisp_Object help_echo_object;
1047 ptrdiff_t help_echo_pos;
1048
1049
1050
1051 Lisp_Object previous_help_echo_string;
1052
1053
1054
1055 #ifdef HAVE_WINDOW_SYSTEM
1056
1057
1058 static bool hourglass_shown_p;
1059
1060
1061
1062 static struct atimer *hourglass_atimer;
1063
1064 #endif
1065
1066
1067
1068 #define DEFAULT_HOURGLASS_DELAY 1
1069
1070 #ifdef HAVE_WINDOW_SYSTEM
1071
1072
1073 #define THIN_SPACE_WIDTH 1
1074
1075 #endif
1076
1077
1078
1079 static void setup_for_ellipsis (struct it *, int);
1080 static void set_iterator_to_next (struct it *, bool);
1081 static void mark_window_display_accurate_1 (struct window *, bool);
1082 static bool row_for_charpos_p (struct glyph_row *, ptrdiff_t);
1083 static bool cursor_row_p (struct glyph_row *);
1084 static int redisplay_mode_lines (Lisp_Object, bool);
1085
1086 static void handle_line_prefix (struct it *);
1087
1088 static void handle_stop_backwards (struct it *, ptrdiff_t);
1089 static void unwind_with_echo_area_buffer (Lisp_Object);
1090 static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
1091 static bool current_message_1 (void *, Lisp_Object);
1092 static bool truncate_message_1 (void *, Lisp_Object);
1093 static void set_message (Lisp_Object);
1094 static bool set_message_1 (void *, Lisp_Object);
1095 static bool display_echo_area_1 (void *, Lisp_Object);
1096 static bool resize_mini_window_1 (void *, Lisp_Object);
1097 static void unwind_redisplay (void);
1098 static void extend_face_to_end_of_line (struct it *);
1099 static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
1100 static void push_it (struct it *, struct text_pos *);
1101 static void iterate_out_of_display_property (struct it *);
1102 static void pop_it (struct it *);
1103 static void redisplay_internal (void);
1104 static void echo_area_display (bool);
1105 static void block_buffer_flips (void);
1106 static void unblock_buffer_flips (void);
1107 static void redisplay_windows (Lisp_Object);
1108 static void redisplay_window (Lisp_Object, bool);
1109 static Lisp_Object redisplay_window_error (Lisp_Object);
1110 static Lisp_Object redisplay_window_0 (Lisp_Object);
1111 static Lisp_Object redisplay_window_1 (Lisp_Object);
1112 static bool set_cursor_from_row (struct window *, struct glyph_row *,
1113 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
1114 int, int);
1115 static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
1116 static bool update_menu_bar (struct frame *, bool, bool);
1117 static bool try_window_reusing_current_matrix (struct window *);
1118 static int try_window_id (struct window *);
1119 static void maybe_produce_line_number (struct it *);
1120 static bool should_produce_line_number (struct it *);
1121 static bool display_line (struct it *, int);
1122 static int display_mode_lines (struct window *);
1123 static int display_mode_line (struct window *, enum face_id, Lisp_Object);
1124 static int display_mode_element (struct it *, int, int, int, Lisp_Object,
1125 Lisp_Object, bool);
1126 static int store_mode_line_string (const char *, Lisp_Object, bool, int, int,
1127 Lisp_Object);
1128 static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
1129 static void display_menu_bar (struct window *);
1130 static void display_tab_bar (struct window *);
1131 static void update_tab_bar (struct frame *, bool);
1132 static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t,
1133 ptrdiff_t *);
1134 static void pint2str (register char *, register int, register ptrdiff_t);
1135
1136 static int display_string (const char *, Lisp_Object, Lisp_Object,
1137 ptrdiff_t, ptrdiff_t, struct it *, int, int, int,
1138 int);
1139 static void compute_line_metrics (struct it *);
1140 static bool get_overlay_strings (struct it *, ptrdiff_t);
1141 static bool get_overlay_strings_1 (struct it *, ptrdiff_t, bool);
1142 static void next_overlay_string (struct it *);
1143 static void reseat (struct it *, struct text_pos, bool);
1144 static void reseat_1 (struct it *, struct text_pos, bool);
1145 static bool next_element_from_display_vector (struct it *);
1146 static bool next_element_from_string (struct it *);
1147 static bool next_element_from_c_string (struct it *);
1148 static bool next_element_from_buffer (struct it *);
1149 static bool next_element_from_composition (struct it *);
1150 static bool next_element_from_image (struct it *);
1151 static bool next_element_from_stretch (struct it *);
1152 static bool next_element_from_xwidget (struct it *);
1153 static void load_overlay_strings (struct it *, ptrdiff_t);
1154 static bool get_next_display_element (struct it *);
1155 static enum move_it_result
1156 move_it_in_display_line_to (struct it *, ptrdiff_t, int,
1157 enum move_operation_enum);
1158 static void get_visually_first_element (struct it *);
1159 static void compute_stop_pos (struct it *);
1160 static int face_before_or_after_it_pos (struct it *, bool);
1161 static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
1162 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
1163 static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
1164 Lisp_Object, struct text_pos *,
1165 ptrdiff_t, int, bool, bool);
1166 static int underlying_face_id (const struct it *);
1167
1168 #define face_before_it_pos(IT) face_before_or_after_it_pos (IT, true)
1169 #define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false)
1170
1171 #ifdef HAVE_WINDOW_SYSTEM
1172
1173 static void update_tool_bar (struct frame *, bool);
1174 static void gui_draw_bottom_divider (struct window *w);
1175 static void notice_overwritten_cursor (struct window *,
1176 enum glyph_row_area,
1177 int, int, int, int);
1178 static int normal_char_height (struct font *, int);
1179 static void normal_char_ascent_descent (struct font *, int, int *, int *);
1180
1181 static void append_stretch_glyph (struct it *, Lisp_Object,
1182 int, int, int);
1183
1184 static Lisp_Object get_it_property (struct it *, Lisp_Object);
1185 static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
1186 struct font *, int, bool);
1187 static int adjust_glyph_width_for_mouse_face (struct glyph *,
1188 struct glyph_row *,
1189 struct window *, struct face *,
1190 struct face *);
1191 static void get_cursor_offset_for_mouse_face (struct window *w,
1192 struct glyph_row *row,
1193 int *offset);
1194 #endif
1195
1196 static void produce_special_glyphs (struct it *, enum display_element_type);
1197 static void pad_mode_line (struct it *, bool);
1198 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
1199 static bool coords_in_mouse_face_p (struct window *, int, int);
1200 static void reset_box_start_end_flags (struct it *);
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214 int
1215 window_text_bottom_y (struct window *w)
1216 {
1217 int height = WINDOW_PIXEL_HEIGHT (w);
1218
1219 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1220
1221 if (window_wants_mode_line (w))
1222 height -= CURRENT_MODE_LINE_HEIGHT (w);
1223
1224 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1225
1226 return height;
1227 }
1228
1229
1230
1231
1232
1233 int
1234 window_box_width (struct window *w, enum glyph_row_area area)
1235 {
1236 int width = w->pixel_width;
1237
1238 if (!w->pseudo_window_p)
1239 {
1240 width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
1241 width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
1242
1243 if (area == TEXT_AREA)
1244 width -= (WINDOW_MARGINS_WIDTH (w)
1245 + WINDOW_FRINGES_WIDTH (w));
1246 else if (area == LEFT_MARGIN_AREA)
1247 width = WINDOW_LEFT_MARGIN_WIDTH (w);
1248 else if (area == RIGHT_MARGIN_AREA)
1249 width = WINDOW_RIGHT_MARGIN_WIDTH (w);
1250 }
1251
1252
1253
1254 return max (0, width);
1255 }
1256
1257
1258
1259
1260
1261 int
1262 window_box_height (struct window *w)
1263 {
1264 struct frame *f = XFRAME (w->frame);
1265 int height = WINDOW_PIXEL_HEIGHT (w);
1266
1267 eassert (height >= 0);
1268
1269 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1270 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1271
1272
1273
1274
1275
1276
1277
1278 if (window_wants_mode_line (w))
1279 {
1280 if (w->mode_line_height >= 0)
1281 height -= w->mode_line_height;
1282 else
1283 {
1284 struct glyph_row *ml_row
1285 = (w->current_matrix && w->current_matrix->rows
1286 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1287 : 0);
1288 if (ml_row && ml_row->mode_line_p)
1289 height -= ml_row->height;
1290 else
1291 height -= estimate_mode_line_height
1292 (f, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w));
1293 }
1294 }
1295
1296 if (window_wants_tab_line (w))
1297 {
1298 if (w->tab_line_height >= 0)
1299 height -= w->tab_line_height;
1300 else
1301 {
1302 struct glyph_row *tl_row
1303 = (w->current_matrix && w->current_matrix->rows
1304 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
1305 : 0);
1306 if (tl_row && tl_row->mode_line_p)
1307 height -= tl_row->height;
1308 else
1309 height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
1310 }
1311 }
1312
1313 if (window_wants_header_line (w))
1314 {
1315 if (w->header_line_height >= 0)
1316 height -= w->header_line_height;
1317 else
1318 {
1319 struct glyph_row *hl_row
1320 = (w->current_matrix && w->current_matrix->rows
1321 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1322 : 0);
1323 if (hl_row && hl_row->mode_line_p)
1324 height -= hl_row->height;
1325 else
1326 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1327 }
1328 }
1329
1330
1331
1332 return max (0, height);
1333 }
1334
1335
1336
1337
1338
1339 int
1340 window_box_left_offset (struct window *w, enum glyph_row_area area)
1341 {
1342 int x;
1343
1344 if (w->pseudo_window_p)
1345 return 0;
1346
1347 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1348
1349 if (area == TEXT_AREA)
1350 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1351 + window_box_width (w, LEFT_MARGIN_AREA));
1352 else if (area == RIGHT_MARGIN_AREA)
1353 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1354 + window_box_width (w, LEFT_MARGIN_AREA)
1355 + window_box_width (w, TEXT_AREA)
1356 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1357 ? 0
1358 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1359 else if (area == LEFT_MARGIN_AREA
1360 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1361 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1362
1363
1364 return min (x, w->pixel_width);
1365 }
1366
1367
1368
1369
1370
1371
1372 static int
1373 window_box_right_offset (struct window *w, enum glyph_row_area area)
1374 {
1375
1376 return min (window_box_left_offset (w, area) + window_box_width (w, area),
1377 w->pixel_width);
1378 }
1379
1380
1381
1382
1383
1384 int
1385 window_box_left (struct window *w, enum glyph_row_area area)
1386 {
1387 struct frame *f = XFRAME (w->frame);
1388 int x;
1389
1390 if (w->pseudo_window_p)
1391 return FRAME_INTERNAL_BORDER_WIDTH (f);
1392
1393 x = (WINDOW_LEFT_EDGE_X (w)
1394 + window_box_left_offset (w, area));
1395
1396 return x;
1397 }
1398
1399
1400
1401
1402
1403
1404 int
1405 window_box_right (struct window *w, enum glyph_row_area area)
1406 {
1407 return window_box_left (w, area) + window_box_width (w, area);
1408 }
1409
1410
1411
1412
1413
1414
1415
1416
1417 void
1418 window_box (struct window *w, enum glyph_row_area area, int *box_x,
1419 int *box_y, int *box_width, int *box_height)
1420 {
1421 if (box_width)
1422 *box_width = window_box_width (w, area);
1423 if (box_height)
1424 *box_height = window_box_height (w);
1425 if (box_x)
1426 *box_x = window_box_left (w, area);
1427 if (box_y)
1428 {
1429 *box_y = WINDOW_TOP_EDGE_Y (w);
1430 if (window_wants_tab_line (w))
1431 *box_y += CURRENT_TAB_LINE_HEIGHT (w);
1432 if (window_wants_header_line (w))
1433 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1434 }
1435 }
1436
1437 #ifdef HAVE_WINDOW_SYSTEM
1438
1439
1440
1441
1442
1443
1444
1445
1446 static void
1447 window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
1448 int *bottom_right_x, int *bottom_right_y)
1449 {
1450 window_box (w, ANY_AREA, top_left_x, top_left_y,
1451 bottom_right_x, bottom_right_y);
1452 *bottom_right_x += *top_left_x;
1453 *bottom_right_y += *top_left_y;
1454 }
1455
1456 #endif
1457
1458
1459
1460
1461
1462
1463
1464
1465 int
1466 line_bottom_y (struct it *it)
1467 {
1468 int line_height = it->max_ascent + it->max_descent;
1469 int line_top_y = it->current_y;
1470
1471 if (line_height == 0)
1472 {
1473 if (last_height)
1474 line_height = last_height;
1475 else if (IT_CHARPOS (*it) < ZV)
1476 {
1477 move_it_by_lines (it, 1);
1478 line_height = (it->max_ascent || it->max_descent
1479 ? it->max_ascent + it->max_descent
1480 : last_height);
1481 }
1482 else
1483 {
1484 struct glyph_row *row = it->glyph_row;
1485
1486
1487 it->glyph_row = NULL;
1488 it->what = IT_CHARACTER;
1489 it->c = ' ';
1490 it->len = 1;
1491 PRODUCE_GLYPHS (it);
1492 line_height = it->ascent + it->descent;
1493 it->glyph_row = row;
1494 }
1495 }
1496
1497 return line_top_y + line_height;
1498 }
1499
1500 DEFUN ("line-pixel-height", Fline_pixel_height,
1501 Sline_pixel_height, 0, 0, 0,
1502 doc:
1503
1504 )
1505 (void)
1506 {
1507 struct it it;
1508 struct text_pos pt;
1509 struct window *w = XWINDOW (selected_window);
1510 struct buffer *old_buffer = NULL;
1511 Lisp_Object result;
1512
1513 if (XBUFFER (w->contents) != current_buffer)
1514 {
1515 old_buffer = current_buffer;
1516 set_buffer_internal_1 (XBUFFER (w->contents));
1517 }
1518 SET_TEXT_POS (pt, PT, PT_BYTE);
1519 void *itdata = bidi_shelve_cache ();
1520 start_display (&it, w, pt);
1521
1522
1523
1524 move_it_by_lines (&it, 0);
1525 it.vpos = it.current_y = 0;
1526 last_height = 0;
1527 result = make_fixnum (line_bottom_y (&it));
1528 if (old_buffer)
1529 set_buffer_internal_1 (old_buffer);
1530
1531 bidi_unshelve_cache (itdata, false);
1532 return result;
1533 }
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549 int
1550 default_line_pixel_height (struct window *w)
1551 {
1552 struct frame *f = WINDOW_XFRAME (w);
1553 int height = FRAME_LINE_HEIGHT (f);
1554
1555 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1556 {
1557 struct buffer *b = XBUFFER (w->contents);
1558 Lisp_Object val = BVAR (b, extra_line_spacing);
1559
1560 if (NILP (val))
1561 val = BVAR (&buffer_defaults, extra_line_spacing);
1562 if (!NILP (val))
1563 {
1564 if (RANGED_FIXNUMP (0, val, INT_MAX))
1565 height += XFIXNAT (val);
1566 else if (FLOATP (val))
1567 {
1568 int addon = XFLOAT_DATA (val) * height + 0.5;
1569
1570 if (addon >= 0)
1571 height += addon;
1572 }
1573 }
1574 else
1575 height += f->extra_line_spacing;
1576 }
1577
1578 return height;
1579 }
1580
1581
1582
1583 static Lisp_Object
1584 string_from_display_spec (Lisp_Object spec)
1585 {
1586 if (VECTORP (spec))
1587 {
1588 for (ptrdiff_t i = 0; i < ASIZE (spec); i++)
1589 if (STRINGP (AREF (spec, i)))
1590 return AREF (spec, i);
1591 }
1592 else
1593 {
1594 for (; CONSP (spec); spec = XCDR (spec))
1595 if (STRINGP (XCAR (spec)))
1596 return XCAR (spec);
1597 }
1598 return spec;
1599 }
1600
1601
1602
1603
1604
1605 static int
1606 window_hscroll_limited (struct window *w, struct frame *f)
1607 {
1608 ptrdiff_t window_hscroll = w->hscroll;
1609 int window_text_width = window_box_width (w, TEXT_AREA);
1610 int colwidth = FRAME_COLUMN_WIDTH (f);
1611
1612 if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
1613 window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
1614
1615 return window_hscroll;
1616 }
1617
1618
1619
1620
1621
1622 static void
1623 reset_box_start_end_flags (struct it *it)
1624 {
1625
1626
1627 if (it->area == TEXT_AREA
1628
1629 && !(it->what == IT_IMAGE && it->image_id < 0))
1630 {
1631
1632
1633
1634
1635 if (it->face_box_p)
1636 it->start_of_box_run_p = false;
1637 it->end_of_box_run_p = false;
1638 }
1639 }
1640
1641
1642
1643
1644
1645
1646
1647 bool
1648 pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1649 int *rtop, int *rbot, int *rowh, int *vpos)
1650 {
1651 struct it it;
1652 void *itdata = bidi_shelve_cache ();
1653 struct text_pos top;
1654 bool visible_p = false;
1655 struct buffer *old_buffer = NULL;
1656 bool r2l = false;
1657
1658 if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
1659 return visible_p;
1660
1661 if (XBUFFER (w->contents) != current_buffer)
1662 {
1663 old_buffer = current_buffer;
1664 set_buffer_internal_1 (XBUFFER (w->contents));
1665 }
1666
1667 SET_TEXT_POS_FROM_MARKER (top, w->start);
1668
1669
1670
1671
1672 if (CHARPOS (top) > ZV || CHARPOS (top) < BEGV)
1673 SET_TEXT_POS (top, BEGV, BEGV_BYTE);
1674
1675
1676
1677 if (charpos >= 0 && CHARPOS (top) > charpos)
1678 return visible_p;
1679
1680
1681
1682
1683
1684
1685
1686
1687 int prev_mode_line_height = w->mode_line_height;
1688 int prev_header_line_height = w->header_line_height;
1689 int prev_tab_line_height = w->tab_line_height;
1690
1691 if (window_wants_mode_line (w))
1692 {
1693 Lisp_Object window_mode_line_format
1694 = window_parameter (w, Qmode_line_format);
1695
1696 w->mode_line_height
1697 = display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
1698 NILP (window_mode_line_format)
1699 ? BVAR (current_buffer, mode_line_format)
1700 : window_mode_line_format);
1701 }
1702
1703 if (window_wants_tab_line (w))
1704 {
1705 Lisp_Object window_tab_line_format
1706 = window_parameter (w, Qtab_line_format);
1707
1708 w->tab_line_height
1709 = display_mode_line (w, TAB_LINE_FACE_ID,
1710 NILP (window_tab_line_format)
1711 ? BVAR (current_buffer, tab_line_format)
1712 : window_tab_line_format);
1713 }
1714
1715 if (window_wants_header_line (w))
1716 {
1717 Lisp_Object window_header_line_format
1718 = window_parameter (w, Qheader_line_format);
1719
1720 w->header_line_height
1721 = display_mode_line (w, HEADER_LINE_FACE_ID,
1722 NILP (window_header_line_format)
1723 ? BVAR (current_buffer, header_line_format)
1724 : window_header_line_format);
1725 }
1726
1727 start_display (&it, w, top);
1728 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
1729 (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
1730
1731
1732
1733 if (!NILP (Vdisplay_line_numbers)
1734 && it.current_x >= it.first_visible_x
1735 && IT_CHARPOS (it) == charpos
1736 && !it.line_number_produced_p)
1737 {
1738
1739
1740
1741 if (!it.lnum_pixel_width)
1742 {
1743 struct it it2;
1744 void *it2data = NULL;
1745
1746 SAVE_IT (it2, it, it2data);
1747 move_it_by_lines (&it, 1);
1748 it2.lnum_pixel_width = it.lnum_pixel_width;
1749 RESTORE_IT (&it, &it2, it2data);
1750 }
1751 it.current_x += it.lnum_pixel_width;
1752 }
1753
1754 if (charpos >= 0
1755 && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
1756 && IT_CHARPOS (it) >= charpos)
1757
1758
1759
1760 || (it.bidi_p && it.bidi_it.scan_dir == -1
1761 && IT_CHARPOS (it) <= charpos)))
1762 {
1763
1764
1765
1766
1767
1768
1769 int top_x = it.current_x;
1770 int top_y = it.current_y;
1771 int window_top_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
1772 int bottom_y;
1773 struct it save_it;
1774 void *save_it_data = NULL;
1775
1776
1777 SAVE_IT (save_it, it, save_it_data);
1778 last_height = 0;
1779 bottom_y = line_bottom_y (&it);
1780 if (top_y < window_top_y)
1781 visible_p = bottom_y > window_top_y;
1782 else if (top_y < it.last_visible_y)
1783 visible_p = true;
1784 if (bottom_y >= it.last_visible_y
1785 && it.bidi_p && it.bidi_it.scan_dir == -1
1786 && IT_CHARPOS (it) < charpos)
1787 {
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798 int ten_more_lines = 10 * default_line_pixel_height (w);
1799
1800 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1801 MOVE_TO_POS | MOVE_TO_Y);
1802 if (it.current_y > top_y)
1803 visible_p = false;
1804
1805 }
1806 RESTORE_IT (&it, &save_it, save_it_data);
1807 if (visible_p)
1808 {
1809 if (it.method == GET_FROM_DISPLAY_VECTOR)
1810 {
1811
1812
1813 if (charpos < 2 || top.charpos >= charpos)
1814 top_x = it.glyph_row->x;
1815 else
1816 {
1817 struct it it2, it2_prev;
1818
1819
1820
1821
1822
1823
1824 start_display (&it2, w, top);
1825 it2.glyph_row = NULL;
1826 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
1827
1828
1829
1830
1831 if (IT_CHARPOS (it2) != charpos - 1)
1832 it2_prev = it2;
1833 else
1834 {
1835
1836
1837
1838 do {
1839 get_next_display_element (&it2);
1840 PRODUCE_GLYPHS (&it2);
1841 it2_prev = it2;
1842 set_iterator_to_next (&it2, true);
1843 } while (it2.method == GET_FROM_DISPLAY_VECTOR
1844 && IT_CHARPOS (it2) < charpos);
1845 }
1846 if (ITERATOR_AT_END_OF_LINE_P (&it2_prev)
1847 || it2_prev.current_x > it2_prev.last_visible_x)
1848 top_x = it.glyph_row->x;
1849 else
1850 {
1851 top_x = it2_prev.current_x;
1852 top_y = it2_prev.current_y;
1853 }
1854 }
1855 }
1856 else if (IT_CHARPOS (it) != charpos)
1857 {
1858 Lisp_Object cpos = make_fixnum (charpos);
1859 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1860 Lisp_Object string = string_from_display_spec (spec);
1861 struct text_pos tpos;
1862 bool newline_in_string
1863 = (STRINGP (string)
1864 && memchr (SDATA (string), '\n', SBYTES (string)));
1865
1866 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1867 bool replacing_spec_p
1868 = (!NILP (spec)
1869 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1870 charpos, FRAME_WINDOW_P (it.f)));
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887 if (replacing_spec_p)
1888 {
1889 Lisp_Object startpos, endpos;
1890 EMACS_INT start, end;
1891 struct it it3;
1892
1893
1894
1895 endpos =
1896 Fnext_single_char_property_change (cpos, Qdisplay,
1897 Qnil, Qnil);
1898 startpos =
1899 Fprevious_single_char_property_change (endpos, Qdisplay,
1900 Qnil, Qnil);
1901 start = XFIXNAT (startpos);
1902 end = XFIXNAT (endpos);
1903
1904
1905 start_display (&it3, w, top);
1906 if (start > CHARPOS (top))
1907 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
1908
1909
1910
1911
1912 if (it3.method == GET_FROM_BUFFER
1913 && (it3.c == '\n'
1914 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1915 move_it_by_lines (&it3, 1);
1916 else if (move_it_in_display_line_to (&it3, -1,
1917 it3.current_x
1918 + it3.pixel_width,
1919 MOVE_TO_X)
1920 == MOVE_LINE_CONTINUED)
1921 {
1922 move_it_by_lines (&it3, 1);
1923
1924
1925
1926 if (it3.line_wrap == WORD_WRAP)
1927 move_it_by_lines (&it3, -1);
1928 }
1929
1930
1931
1932 top_y = it3.current_y;
1933 if (it3.bidi_p)
1934 {
1935
1936
1937
1938
1939
1940 start_display (&it3, w, top);
1941 move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
1942 if (it3.current_y < top_y)
1943 top_y = it3.current_y;
1944 }
1945
1946
1947
1948 start_display (&it3, w, top);
1949 it3.glyph_row = NULL;
1950 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
1951
1952
1953
1954
1955
1956
1957
1958 bool it3_moved = false;
1959 int top_x_before_string = it3.current_x;
1960
1961
1962
1963
1964
1965 while (get_next_display_element (&it3))
1966 {
1967 if (!EQ (it3.object, string))
1968 top_x_before_string = it3.current_x;
1969 PRODUCE_GLYPHS (&it3);
1970 if ((it3.bidi_it.scan_dir == 1
1971 && IT_CHARPOS (it3) >= charpos)
1972 || (it3.bidi_it.scan_dir == -1
1973 && IT_CHARPOS (it3) <= charpos)
1974 || ITERATOR_AT_END_OF_LINE_P (&it3))
1975 break;
1976 it3_moved = true;
1977 set_iterator_to_next (&it3, false);
1978 }
1979 top_x = it3.current_x - it3.pixel_width;
1980
1981
1982
1983 if (!it3.line_number_produced_p)
1984 {
1985 if (it3.lnum_pixel_width > 0)
1986 {
1987 top_x += it3.lnum_pixel_width;
1988 top_x_before_string += it3.lnum_pixel_width;
1989 }
1990 else if (it.line_number_produced_p)
1991 {
1992 top_x += it.lnum_pixel_width;
1993 top_x_before_string += it3.lnum_pixel_width;
1994 }
1995 }
1996
1997
1998
1999
2000
2001
2002 if (it3_moved
2003 && newline_in_string
2004 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
2005 top_x = top_x_before_string;
2006 }
2007 }
2008
2009 *x = top_x;
2010
2011
2012
2013
2014 if (it.ascent == 0 && it.what == IT_IMAGE
2015 && it.method != GET_FROM_IMAGE
2016 && it.image_id < 0
2017 && it.max_ascent > 0)
2018 *y = max (top_y, window_top_y);
2019 else
2020 *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
2021 *rtop = max (0, window_top_y - top_y);
2022 *rbot = max (0, bottom_y - it.last_visible_y);
2023 *rowh = max (0, (min (bottom_y, it.last_visible_y)
2024 - max (top_y, window_top_y)));
2025 *vpos = it.vpos;
2026 if (it.bidi_it.paragraph_dir == R2L)
2027 r2l = true;
2028 }
2029 }
2030 else
2031 {
2032
2033
2034
2035 struct it it2;
2036 void *it2data = NULL;
2037
2038 SAVE_IT (it2, it, it2data);
2039 if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
2040 move_it_by_lines (&it, 1);
2041 if (charpos < IT_CHARPOS (it)
2042 || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
2043 {
2044 visible_p = true;
2045 RESTORE_IT (&it2, &it2, it2data);
2046 move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
2047 *x = it2.current_x;
2048 if (it2.ascent == 0 && it2.what == IT_IMAGE
2049 && it2.method != GET_FROM_IMAGE
2050 && it2.image_id < 0
2051 && it2.max_ascent > 0)
2052 *y = it2.current_y;
2053 else
2054 *y = it2.current_y + it2.max_ascent - it2.ascent;
2055 *rtop = max (0, -it2.current_y);
2056 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
2057 - it.last_visible_y));
2058 *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
2059 it.last_visible_y)
2060 - max (max (it2.current_y,
2061 WINDOW_TAB_LINE_HEIGHT (w)),
2062 WINDOW_HEADER_LINE_HEIGHT (w))));
2063 *vpos = it2.vpos;
2064 if (it2.bidi_it.paragraph_dir == R2L)
2065 r2l = true;
2066 }
2067 else
2068 bidi_unshelve_cache (it2data, true);
2069 }
2070 bidi_unshelve_cache (itdata, false);
2071
2072 if (old_buffer)
2073 set_buffer_internal_1 (old_buffer);
2074
2075 if (visible_p)
2076 {
2077 if (w->hscroll > 0)
2078 *x -=
2079 window_hscroll_limited (w, WINDOW_XFRAME (w))
2080 * WINDOW_FRAME_COLUMN_WIDTH (w);
2081
2082
2083
2084
2085
2086 if (r2l)
2087 *x = window_box_width (w, TEXT_AREA) - *x - 1;
2088 }
2089
2090 #if false
2091
2092 if (visible_p)
2093 fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
2094 charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
2095 else
2096 fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
2097 #endif
2098
2099
2100 w->mode_line_height = prev_mode_line_height;
2101 w->header_line_height = prev_header_line_height;
2102 w->tab_line_height = prev_tab_line_height;
2103
2104 return visible_p;
2105 }
2106
2107
2108
2109
2110
2111
2112
2113 static int
2114 check_char_and_length (const unsigned char *str, int *len)
2115 {
2116 int c = string_char_and_length (str, len);
2117 if (!CHAR_VALID_P (c))
2118
2119
2120
2121 c = '?';
2122
2123 return c;
2124 }
2125
2126
2127
2128
2129
2130
2131 static struct text_pos
2132 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
2133 {
2134 eassert (STRINGP (string) && nchars >= 0);
2135
2136 if (STRING_MULTIBYTE (string))
2137 {
2138 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
2139
2140 while (nchars--)
2141 {
2142 int len = BYTES_BY_CHAR_HEAD (*p);
2143 p += len;
2144 CHARPOS (pos) += 1;
2145 BYTEPOS (pos) += len;
2146 }
2147 }
2148 else
2149 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
2150
2151 return pos;
2152 }
2153
2154
2155
2156
2157
2158 static struct text_pos
2159 string_pos (ptrdiff_t charpos, Lisp_Object string)
2160 {
2161 struct text_pos pos;
2162 eassert (STRINGP (string));
2163 eassert (charpos >= 0);
2164 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
2165 return pos;
2166 }
2167
2168
2169
2170
2171
2172
2173 static struct text_pos
2174 c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
2175 {
2176 struct text_pos pos;
2177
2178 eassert (s != NULL);
2179 eassert (charpos >= 0);
2180
2181 if (multibyte_p)
2182 {
2183 SET_TEXT_POS (pos, 0, 0);
2184 while (charpos--)
2185 {
2186 int len = BYTES_BY_CHAR_HEAD (*s);
2187 s += len;
2188 CHARPOS (pos) += 1;
2189 BYTEPOS (pos) += len;
2190 }
2191 }
2192 else
2193 SET_TEXT_POS (pos, charpos, charpos);
2194
2195 return pos;
2196 }
2197
2198
2199
2200
2201
2202 static ptrdiff_t
2203 number_of_chars (const char *s, bool multibyte_p)
2204 {
2205 ptrdiff_t nchars;
2206
2207 if (multibyte_p)
2208 {
2209 ptrdiff_t rest = strlen (s);
2210 const unsigned char *p = (const unsigned char *) s;
2211
2212 for (nchars = 0; rest > 0; ++nchars)
2213 {
2214 int len = BYTES_BY_CHAR_HEAD (*p);
2215 rest -= len, p += len;
2216 }
2217 }
2218 else
2219 nchars = strlen (s);
2220
2221 return nchars;
2222 }
2223
2224
2225
2226
2227
2228
2229 static void
2230 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
2231 {
2232 eassert (STRINGP (string));
2233 eassert (CHARPOS (*newpos) >= CHARPOS (pos));
2234
2235 if (STRING_MULTIBYTE (string))
2236 *newpos = string_pos_nchars_ahead (pos, string,
2237 CHARPOS (*newpos) - CHARPOS (pos));
2238 else
2239 BYTEPOS (*newpos) = CHARPOS (*newpos);
2240 }
2241
2242
2243
2244
2245
2246 int
2247 estimate_mode_line_height (struct frame *f, enum face_id face_id)
2248 {
2249 #ifdef HAVE_WINDOW_SYSTEM
2250 if (FRAME_WINDOW_P (f))
2251 {
2252 int height = FONT_HEIGHT (FRAME_FONT (f));
2253
2254
2255
2256 if (FRAME_FACE_CACHE (f))
2257 {
2258 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2259 if (face)
2260 {
2261 if (face->font)
2262 height = normal_char_height (face->font, -1);
2263 if (face->box_horizontal_line_width > 0)
2264 height += 2 * face->box_horizontal_line_width;
2265 }
2266 }
2267
2268 return height;
2269 }
2270 #endif
2271
2272 return 1;
2273 }
2274
2275
2276
2277
2278
2279
2280 void
2281 pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2282 NativeRectangle *bounds, bool noclip)
2283 {
2284
2285 #ifdef HAVE_WINDOW_SYSTEM
2286 if (FRAME_WINDOW_P (f))
2287 {
2288
2289
2290 if (pix_x < 0)
2291 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
2292 if (pix_y < 0)
2293 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
2294
2295 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
2296 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
2297
2298 if (bounds)
2299 STORE_NATIVE_RECT (*bounds,
2300 FRAME_COL_TO_PIXEL_X (f, pix_x),
2301 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
2302 FRAME_COLUMN_WIDTH (f) - 1,
2303 FRAME_LINE_HEIGHT (f) - 1);
2304
2305
2306 if (!noclip)
2307 {
2308 if (pix_x < 0)
2309 pix_x = 0;
2310 else if (pix_x > FRAME_TOTAL_COLS (f))
2311 pix_x = FRAME_TOTAL_COLS (f);
2312
2313 if (pix_y < 0)
2314 pix_y = 0;
2315 else if (pix_y > FRAME_TOTAL_LINES (f))
2316 pix_y = FRAME_TOTAL_LINES (f);
2317 }
2318 }
2319 #endif
2320
2321 *x = pix_x;
2322 *y = pix_y;
2323 }
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334 struct glyph *
2335 x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2336 int *dx, int *dy, int *area)
2337 {
2338 struct glyph *glyph, *end;
2339 struct glyph_row *row = NULL;
2340 int x0, i;
2341
2342
2343 for (i = 0; i < w->current_matrix->nrows; ++i)
2344 {
2345 row = MATRIX_ROW (w->current_matrix, i);
2346 if (!row->enabled_p)
2347 return NULL;
2348 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
2349 break;
2350 }
2351
2352 *vpos = i;
2353 *hpos = 0;
2354
2355
2356 if (i == w->current_matrix->nrows)
2357 return NULL;
2358
2359
2360 if (w->pseudo_window_p)
2361 {
2362 *area = TEXT_AREA;
2363 x0 = 0;
2364 }
2365 else
2366 {
2367 if (x < window_box_left_offset (w, TEXT_AREA))
2368 {
2369 *area = LEFT_MARGIN_AREA;
2370 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
2371 }
2372 else if (x < window_box_right_offset (w, TEXT_AREA))
2373 {
2374 *area = TEXT_AREA;
2375 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
2376 }
2377 else
2378 {
2379 *area = RIGHT_MARGIN_AREA;
2380 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
2381 }
2382 }
2383
2384
2385 glyph = row->glyphs[*area];
2386 end = glyph + row->used[*area];
2387 x -= x0;
2388 while (glyph < end && x >= glyph->pixel_width)
2389 {
2390 x -= glyph->pixel_width;
2391 ++glyph;
2392 }
2393
2394 if (glyph == end)
2395 return NULL;
2396
2397 if (dx)
2398 {
2399 *dx = x;
2400 *dy = y - (row->y + row->ascent - glyph->ascent);
2401 }
2402
2403 *hpos = glyph - row->glyphs[*area];
2404 return glyph;
2405 }
2406
2407
2408
2409
2410 static void
2411 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
2412 {
2413 if (w->pseudo_window_p)
2414 {
2415
2416
2417 struct frame *f = XFRAME (w->frame);
2418 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
2419 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2420 }
2421 else
2422 {
2423 *x -= WINDOW_LEFT_EDGE_X (w);
2424 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2425 }
2426 }
2427
2428 #ifdef HAVE_WINDOW_SYSTEM
2429
2430
2431
2432
2433
2434 int
2435 get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int n)
2436 {
2437 Emacs_Rectangle r;
2438
2439 if (n <= 0)
2440 return 0;
2441
2442 if (s->row->full_width_p)
2443 {
2444
2445 r.x = WINDOW_LEFT_EDGE_X (s->w);
2446 if (s->row->mode_line_p)
2447 r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
2448 else
2449 r.width = WINDOW_PIXEL_WIDTH (s->w);
2450
2451
2452
2453 if (s->w->pseudo_window_p)
2454 r.height = s->row->visible_height;
2455 else
2456 r.height = s->height;
2457 }
2458 else
2459 {
2460
2461 r.x = window_box_left (s->w, s->area);
2462 r.width = window_box_width (s->w, s->area);
2463 r.height = s->row->visible_height;
2464 }
2465
2466 if (s->clip_head)
2467 if (r.x < s->clip_head->x)
2468 {
2469 if (r.width >= s->clip_head->x - r.x)
2470 r.width -= s->clip_head->x - r.x;
2471 else
2472 r.width = 0;
2473 r.x = s->clip_head->x;
2474 }
2475 if (s->clip_tail)
2476 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
2477 {
2478 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2479 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
2480 else
2481 r.width = 0;
2482 }
2483
2484
2485
2486
2487 if (s->for_overlaps)
2488 {
2489 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2490 r.height = window_text_bottom_y (s->w) - r.y;
2491
2492
2493
2494
2495
2496
2497 if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
2498 {
2499 Emacs_Rectangle rc, r_save = r;
2500
2501 rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
2502 rc.y = s->w->phys_cursor.y;
2503 rc.width = s->w->phys_cursor_width;
2504 rc.height = s->w->phys_cursor_height;
2505
2506 gui_intersect_rectangles (&r_save, &rc, &r);
2507 }
2508 }
2509 else
2510 {
2511
2512
2513
2514 if (!s->row->full_width_p
2515 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2516 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2517 else
2518 r.y = max (0, s->row->y);
2519 }
2520
2521 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
2522
2523
2524
2525 if (s->hl == DRAW_CURSOR)
2526 {
2527 struct glyph *glyph = s->first_glyph;
2528 int height, max_y;
2529
2530 if (s->x > r.x)
2531 {
2532 if (r.width >= s->x - r.x)
2533 r.width -= s->x - r.x;
2534 else
2535 r.width = 0;
2536 r.x = s->x;
2537 }
2538 r.width = min (r.width, glyph->pixel_width);
2539
2540
2541 height = min (glyph->ascent + glyph->descent,
2542 min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
2543 max_y = window_text_bottom_y (s->w) - height;
2544 max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
2545 if (s->ybase - glyph->ascent > max_y)
2546 {
2547 r.y = max_y;
2548 r.height = height;
2549 }
2550 else
2551 {
2552
2553 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2554 if (height < r.height)
2555 {
2556 max_y = r.y + r.height;
2557 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2558 r.height = min (max_y - r.y, height);
2559 }
2560 }
2561 }
2562
2563 if (s->row->clip)
2564 {
2565 Emacs_Rectangle r_save = r;
2566
2567 if (! gui_intersect_rectangles (&r_save, s->row->clip, &r))
2568 r.width = 0;
2569 }
2570
2571 if ((s->for_overlaps & OVERLAPS_BOTH) == 0
2572 || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
2573 {
2574 #ifdef CONVERT_FROM_EMACS_RECT
2575 CONVERT_FROM_EMACS_RECT (r, *rects);
2576 #else
2577 *rects = r;
2578 #endif
2579 return 1;
2580 }
2581 else
2582 {
2583
2584
2585
2586
2587 #ifdef CONVERT_FROM_EMACS_RECT
2588 Emacs_Rectangle rs[2];
2589 #else
2590 Emacs_Rectangle *rs = rects;
2591 #endif
2592 int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
2593
2594 if (s->for_overlaps & OVERLAPS_PRED)
2595 {
2596 rs[i] = r;
2597 if (r.y + r.height > row_y)
2598 {
2599 if (r.y < row_y)
2600 rs[i].height = row_y - r.y;
2601 else
2602 rs[i].height = 0;
2603 }
2604 i++;
2605 }
2606 if (s->for_overlaps & OVERLAPS_SUCC)
2607 {
2608 rs[i] = r;
2609 if (r.y < row_y + s->row->visible_height)
2610 {
2611 if (r.y + r.height > row_y + s->row->visible_height)
2612 {
2613 rs[i].y = row_y + s->row->visible_height;
2614 rs[i].height = r.y + r.height - rs[i].y;
2615 }
2616 else
2617 rs[i].height = 0;
2618 }
2619 i++;
2620 }
2621
2622 n = i;
2623 #ifdef CONVERT_FROM_EMACS_RECT
2624 for (i = 0; i < n; i++)
2625 CONVERT_FROM_EMACS_RECT (rs[i], rects[i]);
2626 #endif
2627 return n;
2628 }
2629 }
2630
2631
2632
2633
2634 void
2635 get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2636 {
2637 get_glyph_string_clip_rects (s, nr, 1);
2638 }
2639
2640
2641
2642
2643
2644
2645
2646 void
2647 get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2648 struct glyph *glyph, int *xp, int *yp, int *heightp)
2649 {
2650 struct frame *f = XFRAME (WINDOW_FRAME (w));
2651 int x, y, wd, h, h0, y0, ascent;
2652
2653
2654
2655
2656
2657 wd = glyph->pixel_width;
2658
2659 x = w->phys_cursor.x;
2660 if (x < 0)
2661 {
2662 wd += x;
2663 x = 0;
2664 }
2665
2666 if (glyph->type == STRETCH_GLYPH
2667 && !x_stretch_cursor_p)
2668 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2669 w->phys_cursor_width = wd;
2670
2671
2672
2673 y = w->phys_cursor.y;
2674 ascent = row->ascent;
2675
2676
2677
2678 if (!row->ends_at_zv_p && row->ascent < glyph->ascent)
2679 {
2680 y -= glyph->ascent - row->ascent;
2681 ascent = glyph->ascent;
2682 }
2683
2684
2685 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2686
2687 h = max (h0, ascent + glyph->descent);
2688
2689
2690 h = min (h, row->height);
2691 h0 = min (h0, ascent + glyph->descent);
2692
2693 y0 = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
2694 if (y < y0)
2695 {
2696 h = max (h - (y0 - y) + 1, h0);
2697 y = y0 - 1;
2698 }
2699 else
2700 {
2701 y0 = window_text_bottom_y (w) - h0;
2702 if (y > y0)
2703 {
2704 h += y - y0;
2705 y = y0;
2706 }
2707 }
2708
2709 *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
2710 *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2711 *heightp = h;
2712 }
2713
2714
2715
2716
2717
2718 void
2719 remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2720 {
2721 Lisp_Object window;
2722 struct window *w;
2723 struct glyph_row *r, *gr, *end_row;
2724 enum window_part part;
2725 enum glyph_row_area area;
2726 int x, y, width, height;
2727
2728 if (mouse_fine_grained_tracking)
2729 {
2730 STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
2731 return;
2732 }
2733
2734
2735
2736
2737 if (window_resize_pixelwise)
2738 {
2739 width = height = 1;
2740 goto virtual_glyph;
2741 }
2742 else if (!f->glyphs_initialized_p
2743 || (window = window_from_coordinates (f, gx, gy, &part, false, false),
2744 NILP (window)))
2745 {
2746 width = FRAME_SMALLEST_CHAR_WIDTH (f);
2747 height = FRAME_SMALLEST_FONT_HEIGHT (f);
2748 goto virtual_glyph;
2749 }
2750
2751 w = XWINDOW (window);
2752 width = WINDOW_FRAME_COLUMN_WIDTH (w);
2753 height = WINDOW_FRAME_LINE_HEIGHT (w);
2754
2755 x = window_relative_x_coord (w, part, gx);
2756 y = gy - WINDOW_TOP_EDGE_Y (w);
2757
2758 r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
2759 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
2760
2761 if (w->pseudo_window_p)
2762 {
2763 area = TEXT_AREA;
2764 part = ON_MODE_LINE;
2765 goto text_glyph;
2766 }
2767
2768 switch (part)
2769 {
2770 case ON_LEFT_MARGIN:
2771 area = LEFT_MARGIN_AREA;
2772 goto text_glyph;
2773
2774 case ON_RIGHT_MARGIN:
2775 area = RIGHT_MARGIN_AREA;
2776 goto text_glyph;
2777
2778 case ON_TAB_LINE:
2779 case ON_HEADER_LINE:
2780 case ON_MODE_LINE:
2781 gr = (part == ON_TAB_LINE
2782 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
2783 : (part == ON_HEADER_LINE
2784 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
2785 : MATRIX_MODE_LINE_ROW (w->current_matrix)));
2786 gy = gr->y;
2787 area = TEXT_AREA;
2788 goto text_glyph_row_found;
2789
2790 case ON_TEXT:
2791 area = TEXT_AREA;
2792
2793 text_glyph:
2794 gr = 0; gy = 0;
2795 for (; r <= end_row && r->enabled_p; ++r)
2796 if (r->y + r->height > y)
2797 {
2798 gr = r; gy = r->y;
2799 break;
2800 }
2801
2802 text_glyph_row_found:
2803 if (gr && gy <= y)
2804 {
2805 struct glyph *g = gr->glyphs[area];
2806 struct glyph *end = g + gr->used[area];
2807
2808 height = gr->height;
2809 for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
2810 if (gx + g->pixel_width > x)
2811 break;
2812
2813 if (g < end)
2814 {
2815 if (g->type == IMAGE_GLYPH)
2816 {
2817
2818
2819 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
2820 return;
2821 }
2822 width = g->pixel_width;
2823 }
2824 else
2825 {
2826
2827 x -= gx;
2828 gx += (x / width) * width;
2829 }
2830
2831 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2832 && part != ON_TAB_LINE)
2833 {
2834 gx += window_box_left_offset (w, area);
2835
2836
2837 height = min (height,
2838 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2839 }
2840 }
2841 else
2842 {
2843
2844 gx = (x / width) * width;
2845 y -= gy;
2846 gy += (y / height) * height;
2847 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2848 && part != ON_TAB_LINE)
2849
2850 height = min (height,
2851 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2852 }
2853 break;
2854
2855 case ON_LEFT_FRINGE:
2856 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2857 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2858 : window_box_right_offset (w, LEFT_MARGIN_AREA));
2859 width = WINDOW_LEFT_FRINGE_WIDTH (w);
2860 goto row_glyph;
2861
2862 case ON_RIGHT_FRINGE:
2863 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2864 ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
2865 : window_box_right_offset (w, TEXT_AREA));
2866 if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
2867 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
2868 && !WINDOW_RIGHTMOST_P (w))
2869 if (gx < WINDOW_PIXEL_WIDTH (w) - width)
2870
2871
2872 width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
2873 else
2874 width = WINDOW_PIXEL_WIDTH (w) - gx;
2875 else
2876 width = WINDOW_RIGHT_FRINGE_WIDTH (w);
2877
2878 goto row_glyph;
2879
2880 case ON_VERTICAL_BORDER:
2881 gx = WINDOW_PIXEL_WIDTH (w) - width;
2882 goto row_glyph;
2883
2884 case ON_VERTICAL_SCROLL_BAR:
2885 gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
2886 ? 0
2887 : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
2888 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2889 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
2890 : 0)));
2891 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2892
2893 row_glyph:
2894 gr = 0, gy = 0;
2895 for (; r <= end_row && r->enabled_p; ++r)
2896 if (r->y + r->height > y)
2897 {
2898 gr = r; gy = r->y;
2899 break;
2900 }
2901
2902 if (gr && gy <= y)
2903 height = gr->height;
2904 else
2905 {
2906
2907 y -= gy;
2908 gy += (y / height) * height;
2909 }
2910 break;
2911
2912 case ON_RIGHT_DIVIDER:
2913 gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
2914 width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
2915 gy = 0;
2916
2917 height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2918 goto add_edge;
2919
2920 case ON_BOTTOM_DIVIDER:
2921 gx = 0;
2922 width = WINDOW_PIXEL_WIDTH (w);
2923 gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2924 height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2925 goto add_edge;
2926
2927 default:
2928 ;
2929 virtual_glyph:
2930
2931
2932
2933
2934
2935
2936 if (gx < 0)
2937 gx -= width - 1;
2938 if (gy < 0)
2939 gy -= height - 1;
2940
2941 gx = (gx / width) * width;
2942 gy = (gy / height) * height;
2943
2944 goto store_rect;
2945 }
2946
2947 add_edge:
2948 gx += WINDOW_LEFT_EDGE_X (w);
2949 gy += WINDOW_TOP_EDGE_Y (w);
2950
2951 store_rect:
2952 STORE_NATIVE_RECT (*rect, gx, gy, width, height);
2953
2954
2955 #if false && defined HAVE_X_WINDOWS
2956 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2957 f->output_data.x->normal_gc,
2958 gx, gy, width, height);
2959 #endif
2960 }
2961
2962
2963 #endif
2964
2965 static void
2966 adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
2967 {
2968 eassert (w);
2969 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
2970 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
2971 w->window_end_vpos
2972 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
2973 }
2974
2975 static bool
2976 hscrolling_current_line_p (struct window *w)
2977 {
2978 return (!w->suspend_auto_hscroll
2979 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
2980 Qcurrent_line));
2981 }
2982
2983
2984
2985
2986
2987
2988
2989 static Lisp_Object
2990 safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
2991 {
2992 add_to_log ("Error during redisplay: %S signaled %S",
2993 Flist (nargs, args), arg);
2994 return Qnil;
2995 }
2996
2997
2998
2999
3000
3001 static Lisp_Object
3002 safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
3003 {
3004 Lisp_Object val;
3005
3006 if (inhibit_eval_during_redisplay)
3007 val = Qnil;
3008 else
3009 {
3010 ptrdiff_t i;
3011 specpdl_ref count = SPECPDL_INDEX ();
3012 Lisp_Object *args;
3013 USE_SAFE_ALLOCA;
3014 SAFE_ALLOCA_LISP (args, nargs);
3015
3016 args[0] = func;
3017 for (i = 1; i < nargs; i++)
3018 args[i] = va_arg (ap, Lisp_Object);
3019
3020 specbind (Qinhibit_redisplay, Qt);
3021 if (inhibit_quit)
3022 specbind (Qinhibit_quit, Qt);
3023
3024
3025 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
3026 safe_eval_handler);
3027 val = SAFE_FREE_UNBIND_TO (count, val);
3028 }
3029
3030 return val;
3031 }
3032
3033 Lisp_Object
3034 safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
3035 {
3036 Lisp_Object retval;
3037 va_list ap;
3038
3039 va_start (ap, func);
3040 retval = safe__call (false, nargs, func, ap);
3041 va_end (ap);
3042 return retval;
3043 }
3044
3045
3046
3047
3048 Lisp_Object
3049 safe_call1 (Lisp_Object fn, Lisp_Object arg)
3050 {
3051 return safe_call (2, fn, arg);
3052 }
3053
3054 static Lisp_Object
3055 safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
3056 {
3057 Lisp_Object retval;
3058 va_list ap;
3059
3060 va_start (ap, fn);
3061 retval = safe__call (inhibit_quit, 2, fn, ap);
3062 va_end (ap);
3063 return retval;
3064 }
3065
3066 Lisp_Object
3067 safe_eval (Lisp_Object sexpr)
3068 {
3069 return safe__call1 (false, Qeval, sexpr);
3070 }
3071
3072 static Lisp_Object
3073 safe__eval (bool inhibit_quit, Lisp_Object sexpr)
3074 {
3075 return safe__call1 (inhibit_quit, Qeval, sexpr);
3076 }
3077
3078
3079
3080
3081 Lisp_Object
3082 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
3083 {
3084 return safe_call (3, fn, arg1, arg2);
3085 }
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096 static void
3097 CHECK_IT (struct it *it)
3098 {
3099 #if false
3100 if (it->method == GET_FROM_STRING)
3101 {
3102 eassert (STRINGP (it->string));
3103 eassert (IT_STRING_CHARPOS (*it) >= 0);
3104 }
3105 else
3106 {
3107 eassert (IT_STRING_CHARPOS (*it) < 0);
3108 if (it->method == GET_FROM_BUFFER)
3109 {
3110
3111 eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
3112 }
3113 }
3114
3115 if (it->dpvec)
3116 eassert (it->current.dpvec_index >= 0);
3117 else
3118 eassert (it->current.dpvec_index < 0);
3119 #endif
3120 }
3121
3122
3123
3124
3125
3126 static void
3127 CHECK_WINDOW_END (struct window *w)
3128 {
3129 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3130 if (!MINI_WINDOW_P (w) && w->window_end_valid)
3131 {
3132 struct glyph_row *row;
3133 eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
3134 !row->enabled_p
3135 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
3136 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
3137 }
3138 #endif
3139 }
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164 void
3165 init_iterator (struct it *it, struct window *w,
3166 ptrdiff_t charpos, ptrdiff_t bytepos,
3167 struct glyph_row *row, enum face_id base_face_id)
3168 {
3169 enum face_id remapped_base_face_id = base_face_id;
3170 int body_width = 0, body_height = 0;
3171
3172
3173 eassert (w != NULL && it != NULL);
3174 eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
3175 && charpos <= ZV));
3176
3177
3178
3179
3180
3181 if (!inhibit_free_realized_faces)
3182 {
3183 if (face_change)
3184 {
3185 face_change = false;
3186 XFRAME (w->frame)->face_change = 0;
3187 free_all_realized_faces (Qnil);
3188 }
3189 else if (XFRAME (w->frame)->face_change)
3190 {
3191 XFRAME (w->frame)->face_change = 0;
3192 free_all_realized_faces (w->frame);
3193 }
3194 }
3195
3196
3197 if (! NILP (Vface_remapping_alist))
3198 remapped_base_face_id
3199 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
3200
3201
3202
3203 if (row == NULL)
3204 {
3205 if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
3206 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
3207 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
3208 else if (base_face_id == TAB_LINE_FACE_ID)
3209 row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
3210 else if (base_face_id == HEADER_LINE_FACE_ID)
3211 {
3212
3213 w->desired_matrix->tab_line_p = window_wants_tab_line (w);
3214 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
3215 }
3216 }
3217
3218
3219
3220 memclear (it, sizeof *it);
3221 it->current.overlay_string_index = -1;
3222 it->current.dpvec_index = -1;
3223 it->base_face_id = remapped_base_face_id;
3224 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3225 it->paragraph_embedding = L2R;
3226 it->bidi_it.w = w;
3227
3228
3229 XSETWINDOW (it->window, w);
3230 it->w = w;
3231 it->f = XFRAME (w->frame);
3232
3233 it->cmp_it.id = -1;
3234 it->cmp_it.parent_it = it;
3235
3236 if (max_redisplay_ticks > 0)
3237 update_redisplay_ticks (0, w);
3238
3239
3240 if (base_face_id == DEFAULT_FACE_ID
3241 && FRAME_WINDOW_P (it->f))
3242 {
3243 if (FIXNATP (BVAR (current_buffer, extra_line_spacing)))
3244 it->extra_line_spacing = XFIXNAT (BVAR (current_buffer, extra_line_spacing));
3245 else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
3246 it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
3247 * FRAME_LINE_HEIGHT (it->f));
3248 else if (it->f->extra_line_spacing > 0)
3249 it->extra_line_spacing = it->f->extra_line_spacing;
3250 }
3251
3252
3253
3254
3255
3256 if (FRAME_FACE_CACHE (it->f) == NULL)
3257 init_frame_faces (it->f);
3258 if (FRAME_FACE_CACHE (it->f)->used == 0)
3259 recompute_basic_faces (it->f);
3260
3261 it->override_ascent = -1;
3262
3263
3264 it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
3265
3266
3267
3268
3269 it->selective = (FIXNUMP (BVAR (current_buffer, selective_display))
3270 ? (clip_to_bounds
3271 (-1, XFIXNUM (BVAR (current_buffer, selective_display)),
3272 PTRDIFF_MAX))
3273 : (!NILP (BVAR (current_buffer, selective_display))
3274 ? -1 : 0));
3275 it->selective_display_ellipsis_p
3276 = !NILP (BVAR (current_buffer, selective_display_ellipses));
3277
3278
3279 it->dp = window_display_table (w);
3280
3281
3282 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
3283
3284 it->tab_width = SANE_TAB_WIDTH (current_buffer);
3285
3286
3287 if (TRUNCATE != 0)
3288 it->line_wrap = TRUNCATE;
3289 if (base_face_id == DEFAULT_FACE_ID
3290 && !it->w->hscroll
3291 && (WINDOW_FULL_WIDTH_P (it->w)
3292 || NILP (Vtruncate_partial_width_windows)
3293 || (FIXNUMP (Vtruncate_partial_width_windows)
3294
3295 && (XFIXNUM (Vtruncate_partial_width_windows)
3296 <= WINDOW_TOTAL_COLS (it->w))))
3297 && NILP (BVAR (current_buffer, truncate_lines)))
3298 it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
3299 ? WINDOW_WRAP : WORD_WRAP;
3300
3301
3302
3303
3304
3305
3306
3307 #ifdef HAVE_WINDOW_SYSTEM
3308 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3309 #endif
3310 {
3311 if (it->line_wrap == TRUNCATE)
3312 {
3313
3314 eassert (it->glyph_row == NULL);
3315 produce_special_glyphs (it, IT_TRUNCATION);
3316 it->truncation_pixel_width = it->pixel_width;
3317 }
3318 else
3319 {
3320
3321 eassert (it->glyph_row == NULL);
3322 produce_special_glyphs (it, IT_CONTINUATION);
3323 it->continuation_pixel_width = it->pixel_width;
3324 }
3325 }
3326
3327
3328
3329 it->pixel_width = it->ascent = it->descent = 0;
3330 it->phys_ascent = it->phys_descent = 0;
3331
3332
3333
3334
3335 it->glyph_row = row;
3336 it->area = TEXT_AREA;
3337
3338
3339
3340
3341
3342 if (base_face_id != DEFAULT_FACE_ID)
3343 {
3344
3345 it->first_visible_x = 0;
3346 it->last_visible_x =
3347 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3348 }
3349 else
3350 {
3351
3352
3353
3354
3355
3356
3357 if (hscrolling_current_line_p (w))
3358 {
3359 if (w->min_hscroll > 0)
3360 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
3361 else
3362 it->first_visible_x = 0;
3363 }
3364 else
3365 it->first_visible_x =
3366 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
3367
3368 body_width = window_box_width (w, TEXT_AREA);
3369 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3370 && body_width != w->old_body_pixel_width)
3371 FRAME_WINDOW_CHANGE (it->f) = true;
3372 it->last_visible_x = it->first_visible_x + body_width;
3373
3374
3375
3376
3377 if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
3378 {
3379 if (it->line_wrap == TRUNCATE)
3380 it->last_visible_x -= it->truncation_pixel_width;
3381 else
3382 it->last_visible_x -= it->continuation_pixel_width;
3383 }
3384
3385 it->tab_line_p = window_wants_tab_line (w);
3386 it->header_line_p = window_wants_header_line (w);
3387 body_height = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
3388 it->current_y = body_height + w->vscroll;
3389 }
3390
3391
3392 if (!FRAME_WINDOW_P (it->f)
3393 && !WINDOW_RIGHTMOST_P (it->w))
3394 it->last_visible_x -= 1;
3395
3396 it->last_visible_y = window_text_bottom_y (w);
3397 body_height += it->last_visible_y;
3398 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3399 && body_height != w->old_body_pixel_height)
3400 FRAME_WINDOW_CHANGE (it->f) = true;
3401
3402
3403
3404 if (base_face_id != DEFAULT_FACE_ID)
3405 {
3406 struct face *face;
3407
3408 it->face_id = remapped_base_face_id;
3409
3410
3411
3412 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3413 if (face && face->box != FACE_NO_BOX)
3414 {
3415 int box_thickness = face->box_vertical_line_width;
3416 it->face_box_p = true;
3417 it->start_of_box_run_p = true;
3418
3419
3420 if (box_thickness > 0)
3421 it->last_visible_x -= box_thickness;
3422 }
3423 }
3424
3425
3426
3427 if (charpos >= BUF_BEG (current_buffer))
3428 {
3429 it->stop_charpos = charpos;
3430 it->end_charpos = ZV;
3431 eassert (charpos == BYTE_TO_CHAR (bytepos));
3432 IT_CHARPOS (*it) = charpos;
3433 IT_BYTEPOS (*it) = bytepos;
3434
3435
3436
3437 it->face_id = it->base_face_id;
3438
3439 it->start = it->current;
3440
3441
3442
3443
3444
3445
3446
3447 it->bidi_p =
3448 !redisplay__inhibit_bidi
3449 && !NILP (BVAR (current_buffer, bidi_display_reordering))
3450 && it->multibyte_p;
3451
3452
3453
3454 if (it->bidi_p)
3455 {
3456
3457
3458
3459
3460 if (base_face_id == DEFAULT_FACE_ID
3461 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
3462 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
3463 {
3464 if (it->line_wrap == TRUNCATE)
3465 it->last_visible_x -= it->truncation_pixel_width;
3466 else
3467 it->last_visible_x -= it->continuation_pixel_width;
3468 }
3469
3470
3471 if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3472 Qleft_to_right))
3473 it->paragraph_embedding = L2R;
3474 else if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3475 Qright_to_left))
3476 it->paragraph_embedding = R2L;
3477 else
3478 it->paragraph_embedding = NEUTRAL_DIR;
3479 bidi_unshelve_cache (NULL, false);
3480 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
3481 &it->bidi_it);
3482 }
3483
3484
3485
3486 it->medium_narrowing_begv = 0;
3487
3488
3489 reseat (it, it->current.pos, true);
3490 }
3491
3492 CHECK_IT (it);
3493 }
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581 static int
3582 get_narrowed_width (struct window *w)
3583 {
3584
3585
3586 int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
3587
3588
3589
3590 int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
3591 - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
3592 || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
3593 return fact * max (1, width);
3594 }
3595
3596 static int
3597 get_narrowed_len (struct window *w)
3598 {
3599 int height = window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS);
3600 return get_narrowed_width (w) * max (1, height);
3601 }
3602
3603 static ptrdiff_t
3604 get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
3605 {
3606 int len = get_narrowed_len (w);
3607 return max ((pos / len - 1) * len, BEGV);
3608 }
3609
3610 static ptrdiff_t
3611 get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
3612 {
3613 int len = get_narrowed_len (w);
3614 return min ((pos / len + 1) * len, ZV);
3615 }
3616
3617
3618
3619
3620
3621
3622 static ptrdiff_t
3623 get_nearby_bol_pos (ptrdiff_t pos)
3624 {
3625 ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = pos;
3626 int dist;
3627 for (dist = 500; dist <= 500000; dist *= 10)
3628 {
3629 pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
3630 start = pos - dist < BEGV ? BEGV : pos - dist;
3631 for (cur = start; cur < pos; cur = next)
3632 {
3633 next = find_newline1 (cur, CHAR_TO_BYTE (cur),
3634 pos, pos_bytepos,
3635 1, &found, NULL, false);
3636 if (found)
3637 bol = next;
3638 else
3639 break;
3640 }
3641 if (bol >= BEGV || start == BEGV)
3642 break;
3643 else
3644 pos = pos - dist < BEGV ? BEGV : pos - dist;
3645 }
3646 eassert (bol <= init_pos);
3647 return bol;
3648 }
3649
3650 ptrdiff_t
3651 get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
3652 {
3653 int len = get_narrowed_width (w);
3654 ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
3655 return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
3656 }
3657
3658 ptrdiff_t
3659 get_large_narrowing_begv (ptrdiff_t pos)
3660 {
3661 if (long_line_optimizations_region_size <= 0)
3662 return BEGV;
3663 int len = long_line_optimizations_region_size / 2;
3664 int begv = max (pos - len, BEGV);
3665 int limit = long_line_optimizations_bol_search_limit;
3666 while (limit > 0)
3667 {
3668 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3669 return begv;
3670 begv--;
3671 limit--;
3672 }
3673 return begv;
3674 }
3675
3676 ptrdiff_t
3677 get_large_narrowing_zv (ptrdiff_t pos)
3678 {
3679 if (long_line_optimizations_region_size <= 0)
3680 return ZV;
3681 int len = long_line_optimizations_region_size / 2;
3682 return min (pos + len, ZV);
3683 }
3684
3685 static void
3686 unwind_narrowed_begv (Lisp_Object point_min)
3687 {
3688 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3689 }
3690
3691
3692
3693
3694 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
3695 do { \
3696 if (IT->medium_narrowing_begv) \
3697 { \
3698 specpdl_ref count = SPECPDL_INDEX (); \
3699 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3700 SET_BUF_BEGV (current_buffer, BV); \
3701 DST = EXPR; \
3702 unbind_to (count, Qnil); \
3703 } \
3704 else \
3705 DST = EXPR; \
3706 } while (0)
3707
3708
3709
3710 void
3711 start_display (struct it *it, struct window *w, struct text_pos pos)
3712 {
3713 struct glyph_row *row;
3714 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
3715
3716 row = w->desired_matrix->rows + first_vpos;
3717 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3718 it->first_vpos = first_vpos;
3719
3720
3721
3722 if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
3723 {
3724 int first_y = it->current_y;
3725
3726
3727
3728 bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
3729 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
3730 if (!start_at_line_beg_p)
3731 {
3732 int new_x;
3733
3734 reseat_at_previous_visible_line_start (it);
3735 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
3736
3737 new_x = it->current_x + it->pixel_width;
3738
3739
3740
3741
3742
3743
3744
3745 if (it->current_x > 0
3746 && it->line_wrap != TRUNCATE
3747 && (
3748 new_x > it->last_visible_x
3749
3750
3751 || (new_x == it->last_visible_x
3752 && FRAME_WINDOW_P (it->f)
3753 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
3754 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
3755 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
3756 {
3757 if ((it->current.dpvec_index >= 0
3758 || it->current.overlay_string_index >= 0)
3759
3760
3761
3762
3763
3764 && it->c != '\n')
3765 {
3766 set_iterator_to_next (it, true);
3767 move_it_in_display_line_to (it, -1, -1, 0);
3768 }
3769
3770 it->continuation_lines_width += it->current_x;
3771 }
3772
3773
3774
3775
3776
3777 else if (it->current.dpvec_index >= 0)
3778 it->current.dpvec_index = 0;
3779
3780
3781
3782
3783 it->max_ascent = it->max_descent = 0;
3784 it->max_phys_ascent = it->max_phys_descent = 0;
3785
3786 it->current_y = first_y;
3787 it->vpos = 0;
3788 it->current_x = it->hpos = 0;
3789 }
3790 }
3791 }
3792
3793
3794
3795
3796
3797 static bool
3798 in_ellipses_for_invisible_text_p (struct display_pos *pos, struct window *w)
3799 {
3800 Lisp_Object prop, window;
3801 bool ellipses_p = false;
3802 ptrdiff_t charpos = CHARPOS (pos->pos);
3803
3804
3805
3806
3807
3808 if (pos->dpvec_index >= 0
3809 && pos->overlay_string_index < 0
3810 && CHARPOS (pos->string_pos) < 0
3811 && charpos > BEGV
3812 && (XSETWINDOW (window, w),
3813 prop = Fget_char_property (make_fixnum (charpos),
3814 Qinvisible, window),
3815 TEXT_PROP_MEANS_INVISIBLE (prop) == 0))
3816 {
3817 prop = Fget_char_property (make_fixnum (charpos - 1), Qinvisible,
3818 window);
3819 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
3820 }
3821
3822 return ellipses_p;
3823 }
3824
3825
3826
3827
3828
3829
3830
3831 static bool
3832 init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
3833 {
3834 ptrdiff_t charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3835 int i;
3836 bool overlay_strings_with_newlines = false;
3837
3838
3839
3840
3841
3842 if (in_ellipses_for_invisible_text_p (pos, w))
3843 {
3844 --charpos;
3845 bytepos = 0;
3846 }
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
3858
3859
3860
3861
3862 for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
3863 {
3864 const char *s = SSDATA (it->overlay_strings[i]);
3865 const char *e = s + SBYTES (it->overlay_strings[i]);
3866
3867 while (s < e && *s != '\n')
3868 ++s;
3869
3870 if (s < e)
3871 {
3872 overlay_strings_with_newlines = true;
3873 break;
3874 }
3875 }
3876
3877
3878
3879 if (pos->overlay_string_index >= 0)
3880 {
3881 int relative_index;
3882
3883
3884
3885
3886
3887 if (it->method == GET_FROM_IMAGE)
3888 pop_it (it);
3889
3890
3891
3892
3893 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
3894 {
3895 ptrdiff_t n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
3896 it->current.overlay_string_index = 0;
3897 while (n--)
3898 {
3899 load_overlay_strings (it, 0);
3900 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
3901 }
3902 }
3903
3904 it->current.overlay_string_index = pos->overlay_string_index;
3905 relative_index = (it->current.overlay_string_index
3906 % OVERLAY_STRING_CHUNK_SIZE);
3907 it->string = it->overlay_strings[relative_index];
3908 eassert (STRINGP (it->string));
3909 it->current.string_pos = pos->string_pos;
3910 it->method = GET_FROM_STRING;
3911 it->end_charpos = SCHARS (it->string);
3912
3913 if (it->bidi_p)
3914 {
3915 it->bidi_it.string.lstring = it->string;
3916 it->bidi_it.string.s = NULL;
3917 it->bidi_it.string.schars = SCHARS (it->string);
3918 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
3919 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
3920 it->bidi_it.string.unibyte = !it->multibyte_p;
3921 it->bidi_it.w = it->w;
3922 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3923 FRAME_WINDOW_P (it->f), &it->bidi_it);
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933 if (CHARPOS (pos->string_pos) == 0)
3934 {
3935 get_visually_first_element (it);
3936 if (IT_STRING_CHARPOS (*it) != 0)
3937 do {
3938
3939 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
3940 bidi_move_to_visually_next (&it->bidi_it);
3941 } while (it->bidi_it.charpos != 0);
3942 }
3943 eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
3944 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
3945 }
3946 }
3947
3948 if (CHARPOS (pos->string_pos) >= 0)
3949 {
3950
3951
3952
3953 it->current.string_pos = pos->string_pos;
3954 eassert (STRINGP (it->string));
3955 if (it->bidi_p)
3956 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3957 FRAME_WINDOW_P (it->f), &it->bidi_it);
3958 }
3959
3960
3961
3962 if (pos->dpvec_index >= 0)
3963 {
3964 if (it->dpvec == NULL)
3965 get_next_display_element (it);
3966 eassert (it->dpvec && it->current.dpvec_index == 0);
3967 it->current.dpvec_index = pos->dpvec_index;
3968 }
3969
3970 CHECK_IT (it);
3971 return !overlay_strings_with_newlines;
3972 }
3973
3974
3975
3976
3977
3978 static void
3979 init_to_row_start (struct it *it, struct window *w, struct glyph_row *row)
3980 {
3981 init_from_display_pos (it, w, &row->start);
3982 it->start = row->start;
3983 it->continuation_lines_width = row->continuation_lines_width;
3984 CHECK_IT (it);
3985 }
3986
3987
3988
3989
3990
3991
3992
3993
3994 static bool
3995 init_to_row_end (struct it *it, struct window *w, struct glyph_row *row)
3996 {
3997 bool success = false;
3998
3999 if (init_from_display_pos (it, w, &row->end))
4000 {
4001 if (row->continued_p)
4002 it->continuation_lines_width
4003 = row->continuation_lines_width + row->pixel_width;
4004 CHECK_IT (it);
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014 if (get_next_display_element (it)
4015 && (it->bidi_it.scan_dir == -1 && it->cmp_it.id >= 0))
4016 success = false;
4017 else
4018 success = true;
4019 }
4020
4021 return success;
4022 }
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035 static void
4036 handle_stop (struct it *it)
4037 {
4038 enum prop_handled handled;
4039 bool handle_overlay_change_p;
4040 struct props *p;
4041
4042 it->dpvec = NULL;
4043 it->current.dpvec_index = -1;
4044 handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
4045 it->ellipsis_p = false;
4046
4047
4048 if (it->selective_display_ellipsis_p)
4049 it->saved_face_id = it->face_id;
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093 do
4094 {
4095 handled = HANDLED_NORMALLY;
4096
4097
4098 for (p = it_props; p->handler; ++p)
4099 {
4100 handled = p->handler (it);
4101
4102 if (handled == HANDLED_RECOMPUTE_PROPS)
4103 break;
4104 else if (handled == HANDLED_RETURN)
4105 {
4106
4107
4108 if (!handle_overlay_change_p
4109 || it->sp > 1
4110
4111
4112
4113
4114
4115
4116 || (it->current.overlay_string_index < 0
4117 && !get_overlay_strings_1 (it, 0, false)))
4118 {
4119 if (it->ellipsis_p)
4120 setup_for_ellipsis (it, 0);
4121
4122
4123
4124
4125
4126 if (STRINGP (it->string) && !SCHARS (it->string))
4127 pop_it (it);
4128 return;
4129 }
4130 else if (STRINGP (it->string) && !SCHARS (it->string))
4131 pop_it (it);
4132 else
4133 {
4134 it->string_from_display_prop_p = false;
4135 it->from_disp_prop_p = false;
4136 handle_overlay_change_p = false;
4137 }
4138 handled = HANDLED_RECOMPUTE_PROPS;
4139 break;
4140 }
4141 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
4142 handle_overlay_change_p = false;
4143 }
4144
4145 if (handled != HANDLED_RECOMPUTE_PROPS)
4146 {
4147
4148
4149 if (it->method == GET_FROM_DISPLAY_VECTOR)
4150 handle_overlay_change_p = false;
4151
4152
4153
4154
4155 if (handle_overlay_change_p)
4156 handled = handle_overlay_change (it);
4157 }
4158
4159 if (it->ellipsis_p)
4160 {
4161 setup_for_ellipsis (it, 0);
4162 break;
4163 }
4164 }
4165 while (handled == HANDLED_RECOMPUTE_PROPS);
4166
4167
4168 if (handled == HANDLED_NORMALLY)
4169 compute_stop_pos (it);
4170 }
4171
4172
4173
4174
4175
4176 static void
4177 compute_stop_pos (struct it *it)
4178 {
4179 register INTERVAL iv, next_iv;
4180 Lisp_Object object, limit, position;
4181 ptrdiff_t charpos, bytepos, cmp_limit_pos = -1;
4182
4183 if (STRINGP (it->string))
4184 {
4185
4186
4187 it->stop_charpos = it->end_charpos;
4188 object = it->string;
4189 limit = Qnil;
4190 charpos = IT_STRING_CHARPOS (*it);
4191 bytepos = IT_STRING_BYTEPOS (*it);
4192 }
4193 else
4194 {
4195 ptrdiff_t pos;
4196
4197
4198
4199 if (it->end_charpos > ZV)
4200 it->end_charpos = ZV;
4201 it->stop_charpos = it->end_charpos;
4202
4203
4204
4205
4206
4207 charpos = IT_CHARPOS (*it);
4208 bytepos = IT_BYTEPOS (*it);
4209 pos = next_overlay_change (charpos);
4210 if (pos < it->stop_charpos)
4211 it->stop_charpos = pos;
4212
4213 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
4214 && !NILP (Vauto_composition_mode)
4215 && composition_break_at_point
4216 && charpos < PT && PT < it->stop_charpos)
4217 it->stop_charpos = PT;
4218
4219
4220
4221 XSETBUFFER (object, current_buffer);
4222 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4223
4224
4225
4226
4227
4228
4229 if (!composition_break_at_point
4230 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
4231 && !NILP (Vauto_composition_mode))
4232 {
4233 ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
4234 bool found = false;
4235
4236 if (pos > ZV)
4237 pos = ZV;
4238 if (endpos > ZV)
4239 endpos = ZV;
4240 ptrdiff_t bpos = CHAR_TO_BYTE (pos);
4241 while (pos < endpos)
4242 {
4243 int ch = fetch_char_advance_no_check (&pos, &bpos);
4244 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\f')
4245 {
4246 found = true;
4247 break;
4248 }
4249 }
4250 if (found)
4251 {
4252 pos--;
4253 cmp_limit_pos = pos;
4254 }
4255 else if (it->stop_charpos < endpos)
4256 pos = it->stop_charpos;
4257 else
4258 {
4259
4260 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4261 }
4262 }
4263 limit = make_fixnum (pos);
4264 }
4265
4266
4267
4268 position = make_fixnum (charpos);
4269 iv = validate_interval_range (object, &position, &position, false);
4270 if (iv)
4271 {
4272 Lisp_Object values_here[LAST_PROP_IDX];
4273 struct props *p;
4274
4275
4276 for (p = it_props; p->handler; ++p)
4277 values_here[p->idx] = textget (iv->plist,
4278 builtin_lisp_symbol (p->name));
4279
4280
4281
4282 for (next_iv = next_interval (iv);
4283 (next_iv
4284 && (NILP (limit)
4285 || XFIXNAT (limit) > next_iv->position));
4286 next_iv = next_interval (next_iv))
4287 {
4288 for (p = it_props; p->handler; ++p)
4289 {
4290 Lisp_Object new_value = textget (next_iv->plist,
4291 builtin_lisp_symbol (p->name));
4292 if (!EQ (values_here[p->idx], new_value))
4293 break;
4294 }
4295
4296 if (p->handler)
4297 break;
4298 }
4299
4300 if (next_iv)
4301 {
4302 if (FIXNUMP (limit)
4303 && next_iv->position >= XFIXNAT (limit))
4304
4305 it->stop_charpos = min (XFIXNAT (limit), it->stop_charpos);
4306 else
4307
4308 it->stop_charpos = min (it->stop_charpos, next_iv->position);
4309 }
4310 }
4311
4312 if (it->cmp_it.id < 0
4313 && (STRINGP (it->string)
4314 || ((!it->bidi_p || it->bidi_it.scan_dir >= 0)
4315 && it->cmp_it.stop_pos <= IT_CHARPOS (*it))))
4316 {
4317 ptrdiff_t stoppos = it->end_charpos;
4318
4319
4320
4321
4322 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4323 stoppos = -1;
4324 else if (cmp_limit_pos > 0)
4325 stoppos = cmp_limit_pos;
4326
4327
4328
4329 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
4330 stoppos, it->string, false);
4331 }
4332
4333 eassert (STRINGP (it->string)
4334 || (it->stop_charpos >= BEGV
4335 && it->stop_charpos >= IT_CHARPOS (*it)));
4336 }
4337
4338
4339
4340
4341 #define MAX_DISP_SCAN 250
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355 ptrdiff_t
4356 compute_display_string_pos (struct text_pos *position,
4357 struct bidi_string_data *string,
4358 struct window *w,
4359 bool frame_window_p, int *disp_prop)
4360 {
4361
4362 Lisp_Object object, object1;
4363 Lisp_Object pos, spec, limpos;
4364 bool string_p = string && (STRINGP (string->lstring) || string->s);
4365 ptrdiff_t eob = string_p ? string->schars : ZV;
4366 ptrdiff_t begb = string_p ? 0 : BEGV;
4367 ptrdiff_t bufpos, charpos = CHARPOS (*position);
4368 ptrdiff_t lim =
4369 (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
4370 struct text_pos tpos;
4371 int rv = 0;
4372
4373 if (string && STRINGP (string->lstring))
4374 object1 = object = string->lstring;
4375 else if (w && !string_p)
4376 {
4377 XSETWINDOW (object, w);
4378 object1 = Qnil;
4379 }
4380 else
4381 object1 = object = Qnil;
4382
4383 *disp_prop = 1;
4384
4385 if (charpos >= eob
4386
4387
4388 || string->from_disp_str
4389
4390 || (string->s && !STRINGP (object)))
4391 {
4392 *disp_prop = 0;
4393 return eob;
4394 }
4395
4396
4397
4398 pos = make_fixnum (charpos);
4399 if (STRINGP (object))
4400 bufpos = string->bufpos;
4401 else
4402 bufpos = charpos;
4403 tpos = *position;
4404 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
4405 && (charpos <= begb
4406 || !EQ (Fget_char_property (make_fixnum (charpos - 1), Qdisplay,
4407 object),
4408 spec))
4409 && (rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos, bufpos,
4410 frame_window_p)))
4411 {
4412 if (rv == 2)
4413 *disp_prop = 2;
4414 return charpos;
4415 }
4416
4417
4418
4419 limpos = make_fixnum (lim);
4420 do {
4421 pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos);
4422 CHARPOS (tpos) = XFIXNAT (pos);
4423 if (CHARPOS (tpos) >= lim)
4424 {
4425 *disp_prop = 0;
4426 break;
4427 }
4428 if (STRINGP (object))
4429 BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
4430 else
4431 BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
4432 spec = Fget_char_property (pos, Qdisplay, object);
4433 if (!STRINGP (object))
4434 bufpos = CHARPOS (tpos);
4435 } while (NILP (spec)
4436 || !(rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos,
4437 bufpos, frame_window_p)));
4438 if (rv == 2)
4439 *disp_prop = 2;
4440
4441 return CHARPOS (tpos);
4442 }
4443
4444
4445
4446
4447
4448
4449 ptrdiff_t
4450 compute_display_string_end (ptrdiff_t charpos, struct bidi_string_data *string)
4451 {
4452
4453 Lisp_Object object =
4454 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
4455 Lisp_Object pos = make_fixnum (charpos);
4456 ptrdiff_t eob =
4457 (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
4458
4459 if (charpos >= eob || (string->s && !STRINGP (object)))
4460 return eob;
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476 if (NILP (Fget_char_property (pos, Qdisplay, object)))
4477 return -1;
4478
4479
4480
4481 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
4482
4483 return XFIXNAT (pos);
4484 }
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496 static enum prop_handled
4497 handle_fontified_prop (struct it *it)
4498 {
4499 Lisp_Object prop, pos;
4500 enum prop_handled handled = HANDLED_NORMALLY;
4501
4502 if (!NILP (Vmemory_full))
4503 return handled;
4504
4505
4506
4507
4508
4509 if (!STRINGP (it->string)
4510 && it->s == NULL
4511 && !NILP (Vfontification_functions)
4512 && !(input_was_pending && redisplay_skip_fontification_on_input)
4513 && !NILP (Vrun_hooks)
4514 && (pos = make_fixnum (IT_CHARPOS (*it)),
4515 prop = Fget_char_property (pos, Qfontified, Qnil),
4516
4517
4518 NILP (prop) && IT_CHARPOS (*it) < Z))
4519 {
4520 specpdl_ref count = SPECPDL_INDEX ();
4521 Lisp_Object val;
4522 struct buffer *obuf = current_buffer;
4523 ptrdiff_t begv = BEGV, zv = ZV;
4524 bool old_clip_changed = current_buffer->clip_changed;
4525 bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
4526
4527 val = Vfontification_functions;
4528 specbind (Qfontification_functions, Qnil);
4529
4530 eassert (it->end_charpos == ZV);
4531
4532 if (current_buffer->long_line_optimizations_p
4533 && long_line_optimizations_region_size > 0)
4534 {
4535 ptrdiff_t begv = it->large_narrowing_begv;
4536 ptrdiff_t zv = it->large_narrowing_zv;
4537 ptrdiff_t charpos = IT_CHARPOS (*it);
4538 if (charpos < begv || charpos > zv)
4539 {
4540 begv = get_large_narrowing_begv (charpos);
4541 zv = get_large_narrowing_zv (charpos);
4542 }
4543 if (begv != BEG || zv != Z)
4544 labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
4545 Qlong_line_optimizations_in_fontification_functions);
4546 }
4547
4548
4549
4550 it->f->inhibit_clear_image_cache = true;
4551
4552 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
4553 safe_call1 (val, pos);
4554 else
4555 {
4556 Lisp_Object fns, fn;
4557
4558 fns = Qnil;
4559
4560 for (; CONSP (val); val = XCDR (val))
4561 {
4562 fn = XCAR (val);
4563
4564 if (EQ (fn, Qt))
4565 {
4566
4567
4568
4569
4570
4571 for (fns = Fdefault_value (Qfontification_functions);
4572 CONSP (fns);
4573 fns = XCDR (fns))
4574 {
4575 fn = XCAR (fns);
4576 if (!EQ (fn, Qt))
4577 safe_call1 (fn, pos);
4578 }
4579 }
4580 else
4581 safe_call1 (fn, pos);
4582 }
4583 }
4584
4585 it->f->inhibit_clear_image_cache = saved_inhibit_flag;
4586 unbind_to (count, Qnil);
4587
4588
4589
4590
4591
4592
4593
4594
4595 if (obuf == current_buffer)
4596 {
4597 if (begv == BEGV && zv == ZV)
4598 current_buffer->clip_changed = old_clip_changed;
4599 }
4600
4601
4602 else if (BUFFER_LIVE_P (obuf))
4603 set_buffer_internal_1 (obuf);
4604
4605
4606
4607
4608
4609
4610 it->end_charpos = ZV;
4611
4612
4613
4614
4615 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
4616 handled = HANDLED_RECOMPUTE_PROPS;
4617 }
4618
4619 return handled;
4620 }
4621
4622
4623
4624
4625
4626
4627
4628 static int
4629 face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
4630 {
4631 ptrdiff_t next_stop;
4632
4633 if (!STRINGP (it->string))
4634 {
4635 return face_at_buffer_position (it->w,
4636 IT_CHARPOS (*it),
4637 &next_stop,
4638 (IT_CHARPOS (*it)
4639 + TEXT_PROP_DISTANCE_LIMIT),
4640 false, it->base_face_id,
4641 attr_filter);
4642 }
4643 else
4644 {
4645 int base_face_id;
4646 ptrdiff_t bufpos;
4647 int i;
4648 Lisp_Object from_overlay
4649 = (it->current.overlay_string_index >= 0
4650 ? it->string_overlays[it->current.overlay_string_index
4651 % OVERLAY_STRING_CHUNK_SIZE]
4652 : Qnil);
4653
4654
4655
4656
4657
4658
4659
4660 if (! NILP (from_overlay))
4661 for (i = it->sp - 1; i >= 0; i--)
4662 {
4663 if (it->stack[i].current.overlay_string_index >= 0)
4664 from_overlay
4665 = it->string_overlays[it->stack[i].current.overlay_string_index
4666 % OVERLAY_STRING_CHUNK_SIZE];
4667 else if (! NILP (it->stack[i].from_overlay))
4668 from_overlay = it->stack[i].from_overlay;
4669
4670 if (!NILP (from_overlay))
4671 break;
4672 }
4673
4674 if (! NILP (from_overlay))
4675 {
4676 bufpos = IT_CHARPOS (*it);
4677
4678
4679 base_face_id
4680 = face_for_overlay_string (it->w,
4681 IT_CHARPOS (*it),
4682 &next_stop,
4683 (IT_CHARPOS (*it)
4684 + TEXT_PROP_DISTANCE_LIMIT),
4685 false,
4686 from_overlay, attr_filter);
4687 }
4688 else
4689 {
4690 bufpos = 0;
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708 base_face_id = it->string_from_prefix_prop_p
4709 ? (!NILP (Vface_remapping_alist)
4710 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4711 : DEFAULT_FACE_ID)
4712 : underlying_face_id (it);
4713 }
4714
4715 return face_at_string_position (it->w,
4716 it->string,
4717 IT_STRING_CHARPOS (*it),
4718 bufpos,
4719 &next_stop,
4720 base_face_id, false,
4721 attr_filter);
4722 }
4723 }
4724
4725
4726
4727
4728 static enum prop_handled
4729 handle_face_prop (struct it *it)
4730 {
4731 specpdl_ref count = SPECPDL_INDEX ();
4732
4733
4734
4735 specbind (Qinhibit_quit, Qt);
4736 const int new_face_id = face_at_pos (it, 0);
4737 unbind_to (count, Qnil);
4738
4739
4740
4741
4742
4743
4744
4745
4746 if (new_face_id != it->face_id)
4747 {
4748 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
4749
4750
4751
4752 struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
4753
4754
4755
4756
4757 if (!STRINGP (it->string)
4758 && !old_face
4759 && IT_CHARPOS (*it) > BEG)
4760 {
4761 const int prev_face_id = face_before_it_pos (it);
4762
4763 old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
4764 }
4765
4766
4767
4768
4769 it->face_id = new_face_id;
4770
4771
4772 if (!(it->start_of_box_run_p && old_face && old_face->box))
4773 it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
4774 && (old_face == NULL || !old_face->box));
4775 it->face_box_p = new_face->box != FACE_NO_BOX;
4776 }
4777
4778 return HANDLED_NORMALLY;
4779 }
4780
4781
4782
4783
4784
4785
4786
4787 static int
4788 underlying_face_id (const struct it *it)
4789 {
4790 int face_id = it->base_face_id, i;
4791
4792 eassert (STRINGP (it->string));
4793
4794 for (i = it->sp - 1; i >= 0; --i)
4795 if (NILP (it->stack[i].string))
4796 face_id = it->stack[i].face_id;
4797
4798 return face_id;
4799 }
4800
4801
4802
4803
4804
4805
4806
4807 static int
4808 face_before_or_after_it_pos (struct it *it, bool before_p)
4809 {
4810 int face_id, limit;
4811 ptrdiff_t next_check_charpos;
4812 struct it it_copy;
4813 void *it_copy_data = NULL;
4814
4815 eassert (it->s == NULL);
4816
4817 if (STRINGP (it->string))
4818 {
4819 ptrdiff_t bufpos, charpos;
4820 int base_face_id;
4821
4822
4823
4824
4825
4826 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
4827 || (IT_STRING_CHARPOS (*it) == 0 && before_p)
4828 || it->current_x <= it->first_visible_x)
4829 return it->face_id;
4830
4831 if (!it->bidi_p)
4832 {
4833
4834
4835
4836 if (before_p)
4837 charpos = IT_STRING_CHARPOS (*it) - 1;
4838 else if (it->what == IT_COMPOSITION)
4839
4840
4841 charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars;
4842 else
4843 charpos = IT_STRING_CHARPOS (*it) + 1;
4844 }
4845 else
4846 {
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857 SAVE_IT (it_copy, *it, it_copy_data);
4858 IT_STRING_CHARPOS (it_copy) = 0;
4859 bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
4860 it_copy.bidi_it.scan_dir = 0;
4861
4862 do
4863 {
4864 charpos = it_copy.bidi_it.charpos;
4865 if (charpos >= SCHARS (it->string))
4866 break;
4867 bidi_move_to_visually_next (&it_copy.bidi_it);
4868 }
4869 while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
4870
4871 if (!before_p)
4872 {
4873
4874
4875
4876 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4877
4878
4879
4880 if (it_copy.bidi_it.first_elt)
4881 n++;
4882 while (n--)
4883 bidi_move_to_visually_next (&it_copy.bidi_it);
4884
4885 charpos = it_copy.bidi_it.charpos;
4886 }
4887
4888 RESTORE_IT (it, it, it_copy_data);
4889 }
4890 eassert (0 <= charpos && charpos <= SCHARS (it->string));
4891
4892 if (it->current.overlay_string_index >= 0)
4893 bufpos = IT_CHARPOS (*it);
4894 else
4895 bufpos = 0;
4896
4897 base_face_id = underlying_face_id (it);
4898
4899
4900 face_id = face_at_string_position (it->w, it->string, charpos,
4901 bufpos, &next_check_charpos,
4902 base_face_id, false, 0);
4903
4904
4905
4906
4907 if (STRING_MULTIBYTE (it->string))
4908 {
4909 struct text_pos pos1 = string_pos (charpos, it->string);
4910 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1);
4911 struct face *face = FACE_FROM_ID (it->f, face_id);
4912 int len, c = check_char_and_length (p, &len);
4913 face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string);
4914 }
4915 }
4916 else
4917 {
4918 struct text_pos pos;
4919
4920 if ((IT_CHARPOS (*it) >= ZV && !before_p)
4921 || (IT_CHARPOS (*it) <= BEGV && before_p))
4922 return it->face_id;
4923
4924 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
4925 pos = it->current.pos;
4926
4927 if (!it->bidi_p)
4928 {
4929 if (before_p)
4930 DEC_TEXT_POS (pos, it->multibyte_p);
4931 else
4932 {
4933 if (it->what == IT_COMPOSITION)
4934 {
4935
4936
4937 pos.charpos += it->cmp_it.nchars;
4938 pos.bytepos += it->len;
4939 }
4940 else
4941 INC_TEXT_POS (pos, it->multibyte_p);
4942 }
4943 }
4944 else
4945 {
4946 if (before_p)
4947 {
4948 int current_x;
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959 if (it->current_x <= it->first_visible_x)
4960 return it->face_id;
4961 SAVE_IT (it_copy, *it, it_copy_data);
4962
4963
4964
4965
4966
4967 current_x = it_copy.current_x;
4968 move_it_vertically_backward (&it_copy, 0);
4969 move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
4970 pos = it_copy.current.pos;
4971 RESTORE_IT (it, it, it_copy_data);
4972 }
4973 else
4974 {
4975
4976
4977
4978 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4979
4980 it_copy = *it;
4981
4982
4983
4984 if (it->bidi_it.first_elt)
4985 n++;
4986 while (n--)
4987 bidi_move_to_visually_next (&it_copy.bidi_it);
4988
4989 SET_TEXT_POS (pos,
4990 it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
4991 }
4992 }
4993 eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
4994
4995
4996 face_id = face_at_buffer_position (it->w,
4997 CHARPOS (pos),
4998 &next_check_charpos,
4999 limit, false, -1, 0);
5000
5001
5002
5003
5004 if (it->multibyte_p)
5005 {
5006 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
5007 struct face *face = FACE_FROM_ID (it->f, face_id);
5008 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
5009 }
5010 }
5011
5012 return face_id;
5013 }
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024 static enum prop_handled
5025 handle_invisible_prop (struct it *it)
5026 {
5027 enum prop_handled handled = HANDLED_NORMALLY;
5028 int invis;
5029 Lisp_Object prop;
5030
5031 if (STRINGP (it->string))
5032 {
5033 Lisp_Object end_charpos, limit;
5034
5035
5036
5037
5038 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
5039 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5040 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5041
5042 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5043 {
5044
5045
5046 bool display_ellipsis_p = (invis == 2);
5047 ptrdiff_t len, endpos;
5048
5049 handled = HANDLED_RECOMPUTE_PROPS;
5050
5051
5052
5053 endpos = len = SCHARS (it->string);
5054 XSETINT (limit, len);
5055 do
5056 {
5057 end_charpos
5058 = Fnext_single_property_change (end_charpos, Qinvisible,
5059 it->string, limit);
5060
5061
5062 eassert (FIXNUMP (end_charpos));
5063 if (FIXNUMP (end_charpos))
5064 {
5065 endpos = XFIXNAT (end_charpos);
5066 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5067 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5068 if (invis == 2)
5069 display_ellipsis_p = true;
5070 }
5071 else
5072 endpos = len;
5073 }
5074 while (invis != 0 && endpos < len);
5075
5076 if (display_ellipsis_p)
5077 it->ellipsis_p = true;
5078
5079 if (endpos < len)
5080 {
5081
5082 struct text_pos old;
5083 ptrdiff_t oldpos;
5084
5085 old = it->current.string_pos;
5086 oldpos = CHARPOS (old);
5087 if (it->bidi_p)
5088 {
5089 if (it->bidi_it.first_elt
5090 && it->bidi_it.charpos < SCHARS (it->string))
5091 bidi_paragraph_init (it->paragraph_embedding,
5092 &it->bidi_it, true);
5093
5094 do
5095 {
5096 bidi_move_to_visually_next (&it->bidi_it);
5097 }
5098 while (oldpos <= it->bidi_it.charpos
5099 && it->bidi_it.charpos < endpos
5100 && it->bidi_it.charpos < it->bidi_it.string.schars);
5101
5102 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5103 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5104 if (IT_CHARPOS (*it) >= endpos)
5105 it->prev_stop = endpos;
5106 }
5107 else
5108 {
5109 IT_STRING_CHARPOS (*it) = endpos;
5110 compute_string_pos (&it->current.string_pos, old, it->string);
5111 }
5112 }
5113 else
5114 {
5115
5116
5117
5118 if (it->current.overlay_string_index >= 0
5119 && !display_ellipsis_p)
5120 {
5121 next_overlay_string (it);
5122
5123
5124 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5125 }
5126 else
5127 {
5128 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
5129 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5130 }
5131 }
5132 }
5133 }
5134 else
5135 {
5136 ptrdiff_t newpos, next_stop, start_charpos, tem;
5137 Lisp_Object pos, overlay;
5138
5139
5140 tem = start_charpos = IT_CHARPOS (*it);
5141 pos = make_fixnum (tem);
5142 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5143 &overlay);
5144 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5145
5146
5147 if (invis != 0 && start_charpos < it->end_charpos)
5148 {
5149
5150
5151 bool display_ellipsis_p = invis == 2;
5152
5153 handled = HANDLED_RECOMPUTE_PROPS;
5154
5155
5156
5157 do
5158 {
5159
5160
5161
5162
5163
5164 newpos = skip_invisible (tem, &next_stop, ZV, it->window);
5165
5166
5167
5168
5169 if (newpos == tem || newpos >= ZV)
5170 invis = 0;
5171 else
5172 {
5173
5174
5175
5176
5177
5178
5179 pos = make_fixnum (newpos);
5180 prop = Fget_char_property (pos, Qinvisible, it->window);
5181 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5182 }
5183
5184
5185
5186 if (invis != 0)
5187 tem = next_stop;
5188
5189
5190
5191 if (invis == 2)
5192 display_ellipsis_p = true;
5193 }
5194 while (invis != 0);
5195
5196
5197 if (it->bidi_p)
5198 {
5199 ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
5200 bool on_newline
5201 = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
5202 bool after_newline
5203 = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
5204
5205
5206
5207
5208
5209
5210
5211
5212 if (on_newline || after_newline)
5213 {
5214 struct text_pos tpos;
5215 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
5216
5217 SET_TEXT_POS (tpos, newpos, bpos);
5218 reseat_1 (it, tpos, false);
5219
5220
5221
5222
5223
5224 if (on_newline)
5225 {
5226 it->bidi_it.first_elt = false;
5227 it->bidi_it.paragraph_dir = pdir;
5228 it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
5229 it->bidi_it.nchars = 1;
5230 it->bidi_it.ch_len = 1;
5231 }
5232 }
5233 else
5234 {
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5246 {
5247
5248
5249
5250
5251
5252
5253
5254 bidi_paragraph_init (it->paragraph_embedding,
5255 &it->bidi_it, true);
5256 }
5257 do
5258 {
5259 bidi_move_to_visually_next (&it->bidi_it);
5260 }
5261 while (it->stop_charpos <= it->bidi_it.charpos
5262 && it->bidi_it.charpos < newpos);
5263 IT_CHARPOS (*it) = it->bidi_it.charpos;
5264 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5265
5266
5267
5268
5269 if (IT_CHARPOS (*it) >= newpos)
5270 it->prev_stop = newpos;
5271 }
5272 }
5273 else
5274 {
5275 IT_CHARPOS (*it) = newpos;
5276 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
5277 }
5278
5279 if (display_ellipsis_p)
5280 {
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293 if (!STRINGP (it->object))
5294 {
5295 it->position.charpos = newpos - 1;
5296 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5297 }
5298 }
5299
5300
5301
5302
5303
5304
5305
5306 if (NILP (overlay)
5307 && get_overlay_strings (it, it->stop_charpos))
5308 {
5309 handled = HANDLED_RECOMPUTE_PROPS;
5310 if (it->sp > 0)
5311 {
5312 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325 it->stack[it->sp - 1].stop_charpos
5326 = CHARPOS (it->stack[it->sp - 1].current.pos);
5327 }
5328 }
5329 else if (display_ellipsis_p)
5330 {
5331 it->ellipsis_p = true;
5332
5333
5334
5335 handled = HANDLED_RETURN;
5336 }
5337 }
5338 }
5339
5340 return handled;
5341 }
5342
5343
5344
5345
5346
5347 static void
5348 setup_for_ellipsis (struct it *it, int len)
5349 {
5350
5351
5352 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5353 {
5354 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5355 it->dpvec = v->contents;
5356 it->dpend = v->contents + v->header.size;
5357 }
5358 else
5359 {
5360
5361 it->dpvec = default_invis_vector;
5362 it->dpend = default_invis_vector + 3;
5363 }
5364
5365 it->dpvec_char_len = len;
5366 it->current.dpvec_index = 0;
5367 it->dpvec_face_id = -1;
5368
5369
5370
5371
5372
5373
5374
5375
5376 if (it->saved_face_id >= 0)
5377 it->face_id = it->saved_face_id;
5378
5379
5380
5381 if (it->method == GET_FROM_BUFFER)
5382 it->ignore_overlay_strings_at_pos_p = false;
5383
5384 it->method = GET_FROM_DISPLAY_VECTOR;
5385 it->ellipsis_p = true;
5386 }
5387
5388
5389 static Lisp_Object
5390 find_display_property (Lisp_Object disp, Lisp_Object prop)
5391 {
5392 if (NILP (disp))
5393 return Qnil;
5394
5395 if (VECTORP (disp))
5396 {
5397 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5398 {
5399 Lisp_Object elem = AREF (disp, i);
5400 if (CONSP (elem)
5401 && CONSP (XCDR (elem))
5402 && EQ (XCAR (elem), prop))
5403 return XCAR (XCDR (elem));
5404 }
5405 return Qnil;
5406 }
5407
5408 else if (CONSP (disp)
5409 && CONSP (XCAR (disp)))
5410 {
5411 while (!NILP (disp))
5412 {
5413 Lisp_Object elem = XCAR (disp);
5414 if (CONSP (elem)
5415 && CONSP (XCDR (elem))
5416 && EQ (XCAR (elem), prop))
5417 return XCAR (XCDR (elem));
5418
5419
5420
5421 if (CONSP (XCDR (disp)))
5422 disp = XCDR (disp);
5423 else
5424 disp = Qnil;
5425 }
5426 return Qnil;
5427 }
5428
5429 else if (CONSP (disp)
5430 && CONSP (XCDR (disp))
5431 && EQ (XCAR (disp), prop))
5432 return XCAR (XCDR (disp));
5433 else
5434 return Qnil;
5435 }
5436
5437 static Lisp_Object
5438 get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object)
5439 {
5440 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5441 Qdisplay, object),
5442 prop);
5443 }
5444
5445 static void
5446 display_min_width (struct it *it, ptrdiff_t bufpos,
5447 Lisp_Object object, Lisp_Object width_spec)
5448 {
5449
5450
5451 if (!NILP (it->min_width_property)
5452 && !EQ (width_spec, it->min_width_property))
5453 {
5454 if (!it->glyph_row)
5455 return;
5456
5457
5458
5459
5460
5461 if ((bufpos == 0
5462 && !EQ (it->min_width_property,
5463 get_display_property (0, Qmin_width, object)))
5464
5465
5466 || (bufpos > BEGV
5467 && EQ (it->min_width_property,
5468 get_display_property (bufpos - 1, Qmin_width, object))))
5469 {
5470 Lisp_Object w = Qnil;
5471 double width;
5472 #ifdef HAVE_WINDOW_SYSTEM
5473 if (FRAME_WINDOW_P (it->f))
5474 {
5475 struct font *font = NULL;
5476 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5477 font = face->font ? face->font : FRAME_FONT (it->f);
5478 calc_pixel_width_or_height (&width, it,
5479 XCAR (it->min_width_property),
5480 font, true, NULL);
5481 width -= it->current_x - it->min_width_start;
5482 w = list1 (make_int (width));
5483 }
5484 else
5485 #endif
5486 {
5487 calc_pixel_width_or_height (&width, it,
5488 XCAR (it->min_width_property),
5489 NULL, true, NULL);
5490 width -= (it->current_x - it->min_width_start) /
5491 FRAME_COLUMN_WIDTH (it->f);
5492 w = make_int (width);
5493 }
5494
5495
5496 it->object = list3 (Qspace, QCwidth, w);
5497 produce_stretch_glyph (it);
5498 if (it->area == TEXT_AREA)
5499 it->current_x += it->pixel_width;
5500 it->min_width_property = Qnil;
5501 }
5502 }
5503
5504
5505
5506
5507 if (CONSP (width_spec))
5508 {
5509 if (bufpos == BEGV
5510
5511 || (bufpos == 0
5512 && !EQ (it->min_width_property,
5513 get_display_property (0, Qmin_width, object)))
5514
5515 || (bufpos > BEGV
5516 && !EQ (width_spec,
5517 get_display_property (bufpos - 1, Qmin_width, object))))
5518 {
5519 it->min_width_property = width_spec;
5520 it->min_width_start = it->current_x;
5521 }
5522 }
5523 }
5524
5525 DEFUN ("get-display-property", Fget_display_property,
5526 Sget_display_property, 2, 4, 0,
5527 doc:
5528
5529
5530
5531
5532 )
5533 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5534 Lisp_Object properties)
5535 {
5536 if (NILP (properties))
5537 properties = Fget_text_property (position, Qdisplay, object);
5538 else
5539 CHECK_LIST (properties);
5540
5541 return find_display_property (properties, prop);
5542 }
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556 static enum prop_handled
5557 handle_display_prop (struct it *it)
5558 {
5559 Lisp_Object propval, object, overlay;
5560 struct text_pos *position;
5561 ptrdiff_t bufpos;
5562
5563 int display_replaced = 0;
5564
5565 if (STRINGP (it->string))
5566 {
5567 object = it->string;
5568 position = &it->current.string_pos;
5569 bufpos = CHARPOS (it->current.pos);
5570 }
5571 else
5572 {
5573 XSETWINDOW (object, it->w);
5574 position = &it->current.pos;
5575 bufpos = CHARPOS (*position);
5576 }
5577
5578
5579 it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
5580 it->space_width = Qnil;
5581 it->font_height = Qnil;
5582 it->voffset = 0;
5583
5584
5585
5586
5587 if (!it->string_from_display_prop_p)
5588 it->area = TEXT_AREA;
5589
5590 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5591 Qdisplay, object, &overlay);
5592
5593
5594 if (!STRINGP (it->string))
5595 object = it->w->contents;
5596
5597
5598 if (!NILP (it->min_width_property)
5599 && NILP (find_display_property (propval, Qmin_width)))
5600 display_min_width (it, bufpos, object, Qnil);
5601
5602 if (NILP (propval))
5603 return HANDLED_NORMALLY;
5604
5605
5606
5607 display_replaced = handle_display_spec (it, propval, object, overlay,
5608 position, bufpos,
5609 FRAME_WINDOW_P (it->f));
5610 return display_replaced != 0 ? HANDLED_RETURN : HANDLED_NORMALLY;
5611 }
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629 static int
5630 handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5631 Lisp_Object overlay, struct text_pos *position,
5632 ptrdiff_t bufpos, bool frame_window_p)
5633 {
5634 int replacing = 0;
5635 bool enable_eval = true;
5636
5637
5638 if (CONSP (spec) && EQ (XCAR (spec), Qdisable_eval))
5639 {
5640 enable_eval = false;
5641 spec = CONSP (XCDR (spec)) ? XCAR (XCDR (spec)) : Qnil;
5642 }
5643
5644 if (CONSP (spec)
5645
5646 && !EQ (XCAR (spec), Qimage)
5647 #ifdef HAVE_XWIDGETS
5648 && !EQ (XCAR (spec), Qxwidget)
5649 #endif
5650 && !EQ (XCAR (spec), Qspace)
5651 && !EQ (XCAR (spec), Qwhen)
5652 && !EQ (XCAR (spec), Qslice)
5653 && !EQ (XCAR (spec), Qspace_width)
5654 && !EQ (XCAR (spec), Qheight)
5655 && !EQ (XCAR (spec), Qraise)
5656
5657 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5658 && !EQ (XCAR (spec), Qleft_fringe)
5659 && !EQ (XCAR (spec), Qright_fringe)
5660 && !EQ (XCAR (spec), Qmin_width)
5661 && !NILP (XCAR (spec)))
5662 {
5663 for (; CONSP (spec); spec = XCDR (spec))
5664 {
5665 int rv = handle_single_display_spec (it, XCAR (spec), object,
5666 overlay, position, bufpos,
5667 replacing, frame_window_p,
5668 enable_eval);
5669 if (rv != 0)
5670 {
5671 replacing = rv;
5672
5673
5674 if (!it || STRINGP (object))
5675 break;
5676 }
5677 }
5678 }
5679 else if (VECTORP (spec))
5680 {
5681 ptrdiff_t i;
5682 for (i = 0; i < ASIZE (spec); ++i)
5683 {
5684 int rv = handle_single_display_spec (it, AREF (spec, i), object,
5685 overlay, position, bufpos,
5686 replacing, frame_window_p,
5687 enable_eval);
5688 if (rv != 0)
5689 {
5690 replacing = rv;
5691
5692
5693 if (!it || STRINGP (object))
5694 break;
5695 }
5696 }
5697 }
5698 else
5699 replacing = handle_single_display_spec (it, spec, object, overlay, position,
5700 bufpos, 0, frame_window_p,
5701 enable_eval);
5702 return replacing;
5703 }
5704
5705
5706
5707
5708 static struct text_pos
5709 display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
5710 {
5711 Lisp_Object end;
5712 struct text_pos end_pos;
5713
5714 end = Fnext_single_char_property_change (make_fixnum (CHARPOS (start_pos)),
5715 Qdisplay, object, Qnil);
5716 CHARPOS (end_pos) = XFIXNAT (end);
5717 if (STRINGP (object))
5718 compute_string_pos (&end_pos, start_pos, it->string);
5719 else
5720 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFIXNAT (end));
5721
5722 return end_pos;
5723 }
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751 static int
5752 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5753 Lisp_Object overlay, struct text_pos *position,
5754 ptrdiff_t bufpos, int display_replaced,
5755 bool frame_window_p, bool enable_eval_p)
5756 {
5757 Lisp_Object form;
5758 Lisp_Object location, value;
5759 struct text_pos start_pos = *position;
5760 void *itdata = NULL;
5761
5762
5763
5764 form = Qt;
5765 if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
5766 {
5767 spec = XCDR (spec);
5768 if (!CONSP (spec))
5769 return 0;
5770 form = XCAR (spec);
5771 spec = XCDR (spec);
5772 }
5773
5774 if (!NILP (form) && !EQ (form, Qt) && !enable_eval_p)
5775 form = Qnil;
5776 if (!NILP (form) && !EQ (form, Qt))
5777 {
5778 specpdl_ref count = SPECPDL_INDEX ();
5779
5780
5781
5782
5783
5784
5785 if (NILP (object))
5786 XSETBUFFER (object, current_buffer);
5787 specbind (Qobject, object);
5788 specbind (Qposition, make_fixnum (CHARPOS (*position)));
5789 specbind (Qbuffer_position, make_fixnum (bufpos));
5790
5791
5792 itdata = bidi_shelve_cache ();
5793 form = safe_eval (form);
5794 bidi_unshelve_cache (itdata, false);
5795 form = unbind_to (count, form);
5796 }
5797
5798 if (NILP (form))
5799 return 0;
5800
5801
5802 if (CONSP (spec)
5803 && EQ (XCAR (spec), Qheight)
5804 && CONSP (XCDR (spec)))
5805 {
5806 if (it)
5807 {
5808 if (!FRAME_WINDOW_P (it->f))
5809 return 0;
5810
5811 it->font_height = XCAR (XCDR (spec));
5812 if (!NILP (it->font_height))
5813 {
5814 int new_height = -1;
5815
5816 if (CONSP (it->font_height)
5817 && (EQ (XCAR (it->font_height), Qplus)
5818 || EQ (XCAR (it->font_height), Qminus))
5819 && CONSP (XCDR (it->font_height))
5820 && RANGED_FIXNUMP (0, XCAR (XCDR (it->font_height)), INT_MAX))
5821 {
5822
5823 int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
5824 if (EQ (XCAR (it->font_height), Qplus))
5825 steps = - steps;
5826 it->face_id = smaller_face (it->f, it->face_id, steps);
5827 }
5828 else if (FUNCTIONP (it->font_height) && enable_eval_p)
5829 {
5830
5831
5832 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5833 Lisp_Object height;
5834 itdata = bidi_shelve_cache ();
5835 height = safe_call1 (it->font_height,
5836 face->lface[LFACE_HEIGHT_INDEX]);
5837 bidi_unshelve_cache (itdata, false);
5838 if (NUMBERP (height))
5839 new_height = XFLOATINT (height);
5840 }
5841 else if (NUMBERP (it->font_height))
5842 {
5843
5844 struct face *f;
5845
5846 f = FACE_FROM_ID (it->f,
5847 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
5848 new_height = (XFLOATINT (it->font_height)
5849 * XFIXNUM (f->lface[LFACE_HEIGHT_INDEX]));
5850 }
5851 else if (enable_eval_p)
5852 {
5853
5854
5855 specpdl_ref count = SPECPDL_INDEX ();
5856 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5857
5858 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
5859 itdata = bidi_shelve_cache ();
5860 value = safe_eval (it->font_height);
5861 bidi_unshelve_cache (itdata, false);
5862 value = unbind_to (count, value);
5863
5864 if (NUMBERP (value))
5865 new_height = XFLOATINT (value);
5866 }
5867
5868 if (new_height > 0)
5869 it->face_id = face_with_height (it->f, it->face_id, new_height);
5870 }
5871 }
5872
5873 return 0;
5874 }
5875
5876
5877 if (CONSP (spec)
5878 && EQ (XCAR (spec), Qspace_width)
5879 && CONSP (XCDR (spec)))
5880 {
5881 if (it)
5882 {
5883 if (!FRAME_WINDOW_P (it->f))
5884 return 0;
5885
5886 value = XCAR (XCDR (spec));
5887 if (NUMBERP (value) && XFLOATINT (value) > 0)
5888 it->space_width = value;
5889 }
5890
5891 return 0;
5892 }
5893
5894
5895 if (CONSP (spec)
5896 && EQ (XCAR (spec), Qmin_width)
5897 && CONSP (XCDR (spec))
5898 && CONSP (XCAR (XCDR (spec))))
5899 {
5900 if (it)
5901 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5902 return 0;
5903 }
5904
5905
5906 if (CONSP (spec)
5907 && EQ (XCAR (spec), Qslice))
5908 {
5909 Lisp_Object tem;
5910
5911 if (it)
5912 {
5913 if (!FRAME_WINDOW_P (it->f))
5914 return 0;
5915
5916 if (tem = XCDR (spec), CONSP (tem))
5917 {
5918 it->slice.x = XCAR (tem);
5919 if (tem = XCDR (tem), CONSP (tem))
5920 {
5921 it->slice.y = XCAR (tem);
5922 if (tem = XCDR (tem), CONSP (tem))
5923 {
5924 it->slice.width = XCAR (tem);
5925 if (tem = XCDR (tem), CONSP (tem))
5926 it->slice.height = XCAR (tem);
5927 }
5928 }
5929 }
5930 }
5931
5932 return 0;
5933 }
5934
5935
5936 if (CONSP (spec)
5937 && EQ (XCAR (spec), Qraise)
5938 && CONSP (XCDR (spec)))
5939 {
5940 if (it)
5941 {
5942 if (!FRAME_WINDOW_P (it->f))
5943 return 0;
5944
5945 #ifdef HAVE_WINDOW_SYSTEM
5946 value = XCAR (XCDR (spec));
5947 if (NUMBERP (value))
5948 {
5949 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5950 it->voffset = - (XFLOATINT (value)
5951 * (normal_char_height (face->font, -1)));
5952 }
5953 #endif
5954 }
5955
5956 return 0;
5957 }
5958
5959
5960
5961 if (it && it->string_from_display_prop_p)
5962 return 0;
5963
5964
5965
5966 if (it)
5967 {
5968 start_pos = *position;
5969 *position = display_prop_end (it, object, start_pos);
5970
5971
5972
5973
5974
5975
5976
5977 if (!NILP (overlay))
5978 {
5979 ptrdiff_t ovendpos = OVERLAY_END (overlay);
5980
5981
5982
5983
5984
5985
5986
5987 ovendpos = clip_to_bounds (BEGV, ovendpos, ZV);
5988
5989 if (ovendpos > CHARPOS (*position))
5990 SET_TEXT_POS (*position, ovendpos, CHAR_TO_BYTE (ovendpos));
5991 }
5992 }
5993 value = Qnil;
5994
5995
5996
5997 if (it)
5998 it->stop_charpos = position->charpos;
5999
6000
6001
6002 if (CONSP (spec)
6003 && (EQ (XCAR (spec), Qleft_fringe)
6004 || EQ (XCAR (spec), Qright_fringe))
6005 && CONSP (XCDR (spec)))
6006 {
6007 if (it)
6008 {
6009 if (!FRAME_WINDOW_P (it->f))
6010
6011
6012 {
6013
6014
6015
6016
6017 if (it->bidi_p)
6018 {
6019 it->position = *position;
6020 iterate_out_of_display_property (it);
6021 *position = it->position;
6022 }
6023 return 1;
6024 }
6025 }
6026 else if (!frame_window_p)
6027 return 1;
6028
6029 #ifdef HAVE_WINDOW_SYSTEM
6030 value = XCAR (XCDR (spec));
6031 int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
6032 if (! fringe_bitmap)
6033
6034
6035 {
6036 if (it && it->bidi_p)
6037 {
6038 it->position = *position;
6039 iterate_out_of_display_property (it);
6040 *position = it->position;
6041 }
6042 return 1;
6043 }
6044
6045 if (it)
6046 {
6047 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
6048
6049 if (CONSP (XCDR (XCDR (spec))))
6050 {
6051 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
6052 int face_id2;
6053
6054
6055
6056 specpdl_ref count1 = SPECPDL_INDEX ();
6057 specbind (Qinhibit_quit, Qt);
6058 face_id2 = lookup_derived_face (it->w, it->f, face_name,
6059 FRINGE_FACE_ID, false);
6060 unbind_to (count1, Qnil);
6061 if (face_id2 >= 0)
6062 face_id = face_id2;
6063 }
6064
6065
6066
6067 push_it (it, position);
6068
6069 it->area = TEXT_AREA;
6070 it->what = IT_IMAGE;
6071 it->image_id = -1;
6072 it->position = start_pos;
6073 it->object = NILP (object) ? it->w->contents : object;
6074 it->method = GET_FROM_IMAGE;
6075 it->from_overlay = Qnil;
6076 it->face_id = face_id;
6077 it->from_disp_prop_p = true;
6078
6079
6080
6081
6082 *position = start_pos;
6083
6084 if (EQ (XCAR (spec), Qleft_fringe))
6085 {
6086 it->left_user_fringe_bitmap = fringe_bitmap;
6087 it->left_user_fringe_face_id = face_id;
6088 }
6089 else
6090 {
6091 it->right_user_fringe_bitmap = fringe_bitmap;
6092 it->right_user_fringe_face_id = face_id;
6093 }
6094 }
6095 #endif
6096 return 1;
6097 }
6098
6099
6100
6101
6102 location = Qunbound;
6103 if (CONSP (spec) && CONSP (XCAR (spec)))
6104 {
6105 Lisp_Object tem;
6106
6107 value = XCDR (spec);
6108 if (CONSP (value))
6109 value = XCAR (value);
6110
6111 tem = XCAR (spec);
6112 if (EQ (XCAR (tem), Qmargin)
6113 && (tem = XCDR (tem),
6114 tem = CONSP (tem) ? XCAR (tem) : Qnil,
6115 (NILP (tem)
6116 || EQ (tem, Qleft_margin)
6117 || EQ (tem, Qright_margin))))
6118 location = tem;
6119 }
6120
6121 if (BASE_EQ (location, Qunbound))
6122 {
6123 location = Qnil;
6124 value = spec;
6125 }
6126
6127
6128
6129
6130
6131
6132
6133
6134 bool valid_p = (STRINGP (value)
6135 #ifdef HAVE_WINDOW_SYSTEM
6136 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6137 && valid_image_p (value))
6138 #endif
6139 || (CONSP (value) && EQ (XCAR (value), Qspace))
6140 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6141 && valid_xwidget_spec_p (value)));
6142
6143 if (valid_p && display_replaced == 0)
6144 {
6145 int retval = 1;
6146
6147 if (!it)
6148 {
6149
6150
6151
6152 if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
6153 retval = 2;
6154 return retval;
6155 }
6156
6157
6158
6159 push_it (it, position);
6160 it->from_overlay = overlay;
6161 it->from_disp_prop_p = true;
6162
6163 if (NILP (location))
6164 it->area = TEXT_AREA;
6165 else if (EQ (location, Qleft_margin))
6166 it->area = LEFT_MARGIN_AREA;
6167 else
6168 it->area = RIGHT_MARGIN_AREA;
6169
6170 if (STRINGP (value))
6171 {
6172 it->string = value;
6173 it->multibyte_p = STRING_MULTIBYTE (it->string);
6174 it->current.overlay_string_index = -1;
6175 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6176 it->end_charpos = it->string_nchars = SCHARS (it->string);
6177 it->method = GET_FROM_STRING;
6178 it->stop_charpos = 0;
6179 it->prev_stop = 0;
6180 it->base_level_stop = 0;
6181 it->string_from_display_prop_p = true;
6182 it->cmp_it.id = -1;
6183
6184
6185
6186 if (BUFFERP (object))
6187 *position = start_pos;
6188
6189
6190
6191
6192 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6193 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6194 else
6195 it->paragraph_embedding = L2R;
6196
6197
6198 if (it->bidi_p)
6199 {
6200 it->bidi_it.string.lstring = it->string;
6201 it->bidi_it.string.s = NULL;
6202 it->bidi_it.string.schars = it->end_charpos;
6203 it->bidi_it.string.bufpos = bufpos;
6204 it->bidi_it.string.from_disp_str = true;
6205 it->bidi_it.string.unibyte = !it->multibyte_p;
6206 it->bidi_it.w = it->w;
6207 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6208 }
6209 }
6210 else if (CONSP (value) && EQ (XCAR (value), Qspace))
6211 {
6212 it->method = GET_FROM_STRETCH;
6213 it->object = value;
6214 *position = it->position = start_pos;
6215 retval = 1 + (it->area == TEXT_AREA);
6216 }
6217 else if (valid_xwidget_spec_p (value))
6218 {
6219 it->what = IT_XWIDGET;
6220 it->method = GET_FROM_XWIDGET;
6221 it->position = start_pos;
6222 it->object = NILP (object) ? it->w->contents : object;
6223 *position = start_pos;
6224 it->xwidget = lookup_xwidget (value);
6225 }
6226 #ifdef HAVE_WINDOW_SYSTEM
6227 else
6228 {
6229 specpdl_ref count = SPECPDL_INDEX ();
6230
6231 it->what = IT_IMAGE;
6232
6233
6234
6235 specbind (Qinhibit_quit, Qt);
6236 it->image_id = lookup_image (it->f, value, it->face_id);
6237 unbind_to (count, Qnil);
6238 it->position = start_pos;
6239 it->object = NILP (object) ? it->w->contents : object;
6240 it->method = GET_FROM_IMAGE;
6241
6242
6243
6244
6245 *position = start_pos;
6246 }
6247 #endif
6248
6249 return retval;
6250 }
6251
6252
6253
6254 *position = start_pos;
6255 return 0;
6256 }
6257
6258
6259
6260
6261
6262
6263 bool
6264 display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
6265 ptrdiff_t charpos, ptrdiff_t bytepos)
6266 {
6267 bool frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
6268 struct text_pos position;
6269
6270 SET_TEXT_POS (position, charpos, bytepos);
6271 return (handle_display_spec (NULL, prop, Qnil, overlay,
6272 &position, charpos, frame_window_p)
6273 != 0);
6274 }
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285 static bool
6286 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
6287 {
6288 if (EQ (string, prop))
6289 return true;
6290
6291
6292 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
6293 {
6294 prop = XCDR (prop);
6295 if (!CONSP (prop))
6296 return false;
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307 prop = XCDR (prop);
6308 }
6309
6310 if (CONSP (prop))
6311
6312 if (EQ (XCAR (prop), Qmargin))
6313 {
6314 prop = XCDR (prop);
6315 if (!CONSP (prop))
6316 return false;
6317
6318 prop = XCDR (prop);
6319 if (!CONSP (prop))
6320 return false;
6321 }
6322
6323 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
6324 }
6325
6326
6327
6328
6329 static bool
6330 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
6331 {
6332 if (CONSP (prop)
6333 && !EQ (XCAR (prop), Qwhen)
6334 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
6335 {
6336
6337 while (CONSP (prop))
6338 {
6339 if (single_display_spec_string_p (XCAR (prop), string))
6340 return true;
6341 prop = XCDR (prop);
6342 }
6343 }
6344 else if (VECTORP (prop))
6345 {
6346
6347 ptrdiff_t i;
6348 for (i = 0; i < ASIZE (prop); ++i)
6349 if (single_display_spec_string_p (AREF (prop, i), string))
6350 return true;
6351 }
6352 else
6353 return single_display_spec_string_p (prop, string);
6354
6355 return false;
6356 }
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368 static ptrdiff_t
6369 string_buffer_position_lim (Lisp_Object string,
6370 ptrdiff_t from, ptrdiff_t to, bool back_p)
6371 {
6372 Lisp_Object limit, prop, pos;
6373 bool found = false;
6374
6375 pos = make_fixnum (max (from, BEGV));
6376
6377 if (!back_p)
6378 {
6379 limit = make_fixnum (min (to, ZV));
6380 while (!found && !EQ (pos, limit))
6381 {
6382 prop = Fget_char_property (pos, Qdisplay, Qnil);
6383 if (!NILP (prop) && display_prop_string_p (prop, string))
6384 found = true;
6385 else
6386 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
6387 limit);
6388 }
6389 }
6390 else
6391 {
6392 limit = make_fixnum (max (to, BEGV));
6393 while (!found && !EQ (pos, limit))
6394 {
6395 prop = Fget_char_property (pos, Qdisplay, Qnil);
6396 if (!NILP (prop) && display_prop_string_p (prop, string))
6397 found = true;
6398 else
6399 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
6400 limit);
6401 }
6402 }
6403
6404 return found ? XFIXNUM (pos) : 0;
6405 }
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416 static ptrdiff_t
6417 string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6418 {
6419 const int MAX_DISTANCE = 1000;
6420 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6421 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6422 forward_limit, false);
6423
6424 if (!found)
6425 {
6426 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6427 found = string_buffer_position_lim (string, around_charpos,
6428 backward_limit, true);
6429 }
6430 return found;
6431 }
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442 static enum prop_handled
6443 handle_composition_prop (struct it *it)
6444 {
6445 Lisp_Object prop, string;
6446 ptrdiff_t pos, pos_byte, start, end;
6447
6448 if (STRINGP (it->string))
6449 {
6450 unsigned char *s;
6451
6452 pos = IT_STRING_CHARPOS (*it);
6453 pos_byte = IT_STRING_BYTEPOS (*it);
6454 string = it->string;
6455 s = SDATA (string) + pos_byte;
6456 if (STRING_MULTIBYTE (string))
6457 it->c = STRING_CHAR (s);
6458 else
6459 it->c = *s;
6460 }
6461 else
6462 {
6463 pos = IT_CHARPOS (*it);
6464 pos_byte = IT_BYTEPOS (*it);
6465 string = Qnil;
6466 it->c = FETCH_CHAR (pos_byte);
6467 }
6468
6469
6470
6471
6472 if (find_composition (pos, -1, &start, &end, &prop, string)
6473 && composition_valid_p (start, end, prop)
6474 && (STRINGP (it->string) || (PT <= start || PT >= end)))
6475 {
6476 if (start < pos)
6477
6478
6479
6480 return HANDLED_NORMALLY;
6481 if (start != pos)
6482 {
6483 if (STRINGP (it->string))
6484 pos_byte = string_char_to_byte (it->string, start);
6485 else
6486 pos_byte = CHAR_TO_BYTE (start);
6487 }
6488 it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
6489 prop, string);
6490
6491 if (it->cmp_it.id >= 0)
6492 {
6493 it->cmp_it.ch = -1;
6494 it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
6495 it->cmp_it.nglyphs = -1;
6496 }
6497 }
6498
6499 return HANDLED_NORMALLY;
6500 }
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511 struct overlay_entry
6512 {
6513 Lisp_Object overlay;
6514 Lisp_Object string;
6515 EMACS_INT priority;
6516 bool after_string_p;
6517 };
6518
6519
6520
6521
6522
6523 static enum prop_handled
6524 handle_overlay_change (struct it *it)
6525 {
6526 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
6527 return HANDLED_RECOMPUTE_PROPS;
6528 else
6529 return HANDLED_NORMALLY;
6530 }
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540 static void
6541 next_overlay_string (struct it *it)
6542 {
6543 ++it->current.overlay_string_index;
6544 if (it->current.overlay_string_index == it->n_overlay_strings)
6545 {
6546
6547
6548
6549
6550 it->ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
6551 pop_it (it);
6552 eassert (it->sp > 0
6553 || (NILP (it->string)
6554 && it->method == GET_FROM_BUFFER
6555 && it->stop_charpos >= BEGV
6556 && it->stop_charpos <= it->end_charpos));
6557 it->current.overlay_string_index = -1;
6558 it->n_overlay_strings = 0;
6559
6560
6561
6562
6563 if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
6564 pop_it (it);
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574 if (it->overlay_strings_charpos == IT_CHARPOS (*it))
6575 it->ignore_overlay_strings_at_pos_p = true;
6576
6577
6578
6579
6580 if (NILP (it->string)
6581 && IT_CHARPOS (*it) >= it->end_charpos
6582 && it->overlay_strings_charpos >= it->end_charpos)
6583 it->overlay_strings_at_end_processed_p = true;
6584
6585
6586
6587
6588
6589
6590
6591 it->overlay_strings_charpos = -1;
6592 }
6593 else
6594 {
6595
6596
6597
6598
6599
6600
6601 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
6602
6603 if (it->current.overlay_string_index && i == 0)
6604 load_overlay_strings (it, it->overlay_strings_charpos);
6605
6606
6607
6608 it->string = it->overlay_strings[i];
6609 it->multibyte_p = STRING_MULTIBYTE (it->string);
6610 SET_TEXT_POS (it->current.string_pos, 0, 0);
6611 it->method = GET_FROM_STRING;
6612 it->stop_charpos = 0;
6613 it->end_charpos = SCHARS (it->string);
6614 if (it->cmp_it.stop_pos >= 0)
6615 it->cmp_it.stop_pos = 0;
6616 it->prev_stop = 0;
6617 it->base_level_stop = 0;
6618
6619
6620 if (it->bidi_p)
6621 {
6622 it->bidi_it.string.lstring = it->string;
6623 it->bidi_it.string.s = NULL;
6624 it->bidi_it.string.schars = SCHARS (it->string);
6625 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
6626 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6627 it->bidi_it.string.unibyte = !it->multibyte_p;
6628 it->bidi_it.w = it->w;
6629 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6630 }
6631 }
6632
6633 CHECK_IT (it);
6634 }
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653 static int
6654 compare_overlay_entries (const void *e1, const void *e2)
6655 {
6656 struct overlay_entry const *entry1 = e1;
6657 struct overlay_entry const *entry2 = e2;
6658 int result;
6659
6660 if (entry1->after_string_p != entry2->after_string_p)
6661 {
6662
6663
6664 if (EQ (entry1->overlay, entry2->overlay))
6665 result = entry1->after_string_p ? 1 : -1;
6666 else
6667 result = entry1->after_string_p ? -1 : 1;
6668 }
6669 else if (entry1->priority != entry2->priority)
6670 {
6671 if (entry1->after_string_p)
6672
6673 result = entry2->priority < entry1->priority ? -1 : 1;
6674 else
6675
6676 result = entry1->priority < entry2->priority ? -1 : 1;
6677 }
6678 else
6679 result = 0;
6680
6681 return result;
6682 }
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709 static void
6710 load_overlay_strings (struct it *it, ptrdiff_t charpos)
6711 {
6712 ptrdiff_t n = 0;
6713 struct overlay_entry entriesbuf[20];
6714 ptrdiff_t size = ARRAYELTS (entriesbuf);
6715 struct overlay_entry *entries = entriesbuf;
6716 struct itree_node *node;
6717
6718 USE_SAFE_ALLOCA;
6719
6720 if (charpos <= 0)
6721 charpos = IT_CHARPOS (*it);
6722
6723
6724
6725
6726
6727 #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
6728 do \
6729 { \
6730 Lisp_Object priority; \
6731 \
6732 if (n == size) \
6733 { \
6734 struct overlay_entry *old = entries; \
6735 SAFE_NALLOCA (entries, 2, size); \
6736 memcpy (entries, old, size * sizeof *entries); \
6737 size *= 2; \
6738 } \
6739 \
6740 entries[n].string = (STRING); \
6741 entries[n].overlay = (OVERLAY); \
6742 priority = Foverlay_get ((OVERLAY), Qpriority); \
6743 entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
6744 entries[n].after_string_p = (AFTER_P); \
6745 ++n; \
6746 } \
6747 while (false)
6748
6749
6750
6751 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6752 {
6753 Lisp_Object overlay = node->data;
6754 eassert (OVERLAYP (overlay));
6755 ptrdiff_t start = node->begin;
6756 ptrdiff_t end = node->end;
6757
6758
6759
6760 if (end != charpos && start != charpos)
6761 continue;
6762
6763
6764 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6765 if (WINDOWP (window) && XWINDOW (window) != it->w)
6766 continue;
6767
6768
6769
6770
6771 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6772 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6773
6774
6775 Lisp_Object str;
6776 if ((start == charpos || (end == charpos && invis != 0))
6777 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6778 && SCHARS (str))
6779 RECORD_OVERLAY_STRING (overlay, str, false);
6780
6781
6782 if ((end == charpos || (start == charpos && invis != 0))
6783 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6784 && SCHARS (str))
6785 RECORD_OVERLAY_STRING (overlay, str, true);
6786 }
6787
6788 #undef RECORD_OVERLAY_STRING
6789
6790
6791 if (n > 1)
6792 qsort (entries, n, sizeof *entries, compare_overlay_entries);
6793
6794
6795 it->n_overlay_strings = n;
6796 it->overlay_strings_charpos = charpos;
6797
6798
6799
6800
6801 ptrdiff_t j = it->current.overlay_string_index;
6802 for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++)
6803 {
6804 it->overlay_strings[i] = entries[j].string;
6805 it->string_overlays[i] = entries[j].overlay;
6806 }
6807
6808 CHECK_IT (it);
6809 SAFE_FREE ();
6810 }
6811
6812
6813
6814
6815
6816
6817 static bool
6818 get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, bool compute_stop_p)
6819 {
6820
6821
6822
6823
6824
6825
6826
6827 it->current.overlay_string_index = 0;
6828 load_overlay_strings (it, charpos);
6829
6830
6831
6832
6833 if (it->n_overlay_strings)
6834 {
6835
6836
6837
6838 if (compute_stop_p)
6839 compute_stop_pos (it);
6840 eassert (it->face_id >= 0);
6841
6842
6843
6844 eassert (!compute_stop_p || it->sp == 0);
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854 if (!(!it->bidi_p
6855 && STRINGP (it->string) && !SCHARS (it->string)))
6856 push_it (it, NULL);
6857
6858
6859
6860 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6861 it->string = it->overlay_strings[0];
6862 it->from_overlay = Qnil;
6863 it->stop_charpos = 0;
6864 eassert (STRINGP (it->string));
6865 it->end_charpos = SCHARS (it->string);
6866 it->prev_stop = 0;
6867 it->base_level_stop = 0;
6868 it->multibyte_p = STRING_MULTIBYTE (it->string);
6869 it->method = GET_FROM_STRING;
6870 it->from_disp_prop_p = 0;
6871 it->cmp_it.id = -1;
6872
6873
6874
6875 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6876 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6877 else
6878 it->paragraph_embedding = L2R;
6879
6880
6881 if (it->bidi_p)
6882 {
6883 ptrdiff_t pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
6884
6885 it->bidi_it.string.lstring = it->string;
6886 it->bidi_it.string.s = NULL;
6887 it->bidi_it.string.schars = SCHARS (it->string);
6888 it->bidi_it.string.bufpos = pos;
6889 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6890 it->bidi_it.string.unibyte = !it->multibyte_p;
6891 it->bidi_it.w = it->w;
6892 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6893 }
6894 return true;
6895 }
6896
6897 it->current.overlay_string_index = -1;
6898 return false;
6899 }
6900
6901 static bool
6902 get_overlay_strings (struct it *it, ptrdiff_t charpos)
6903 {
6904 it->string = Qnil;
6905 it->method = GET_FROM_BUFFER;
6906
6907 get_overlay_strings_1 (it, charpos, true);
6908
6909 CHECK_IT (it);
6910
6911
6912 return STRINGP (it->string);
6913 }
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927 static void
6928 push_it (struct it *it, struct text_pos *position)
6929 {
6930 struct iterator_stack_entry *p;
6931
6932 eassert (it->sp < IT_STACK_SIZE);
6933 p = it->stack + it->sp;
6934
6935 p->stop_charpos = it->stop_charpos;
6936 p->prev_stop = it->prev_stop;
6937 p->base_level_stop = it->base_level_stop;
6938 p->cmp_it = it->cmp_it;
6939 eassert (it->face_id >= 0);
6940 p->face_id = it->face_id;
6941 p->string = it->string;
6942 p->method = it->method;
6943 p->from_overlay = it->from_overlay;
6944 switch (p->method)
6945 {
6946 case GET_FROM_IMAGE:
6947 p->u.image.object = it->object;
6948 p->u.image.image_id = it->image_id;
6949 p->u.image.slice = it->slice;
6950 break;
6951 case GET_FROM_STRETCH:
6952 p->u.stretch.object = it->object;
6953 break;
6954 case GET_FROM_XWIDGET:
6955 p->u.xwidget.object = it->object;
6956 break;
6957 case GET_FROM_BUFFER:
6958 case GET_FROM_DISPLAY_VECTOR:
6959 case GET_FROM_STRING:
6960 case GET_FROM_C_STRING:
6961 break;
6962 default:
6963 emacs_abort ();
6964 }
6965 p->position = position ? *position : it->position;
6966 p->current = it->current;
6967 p->end_charpos = it->end_charpos;
6968 p->string_nchars = it->string_nchars;
6969 p->area = it->area;
6970 p->multibyte_p = it->multibyte_p;
6971 p->avoid_cursor_p = it->avoid_cursor_p;
6972 p->space_width = it->space_width;
6973 p->font_height = it->font_height;
6974 p->voffset = it->voffset;
6975 p->string_from_display_prop_p = it->string_from_display_prop_p;
6976 p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
6977 p->display_ellipsis_p = false;
6978 p->line_wrap = it->line_wrap;
6979 p->bidi_p = it->bidi_p;
6980 p->paragraph_embedding = it->paragraph_embedding;
6981 p->from_disp_prop_p = it->from_disp_prop_p;
6982 ++it->sp;
6983
6984
6985 if (it->bidi_p)
6986 bidi_push_it (&it->bidi_it);
6987 }
6988
6989 static void
6990 iterate_out_of_display_property (struct it *it)
6991 {
6992 bool buffer_p = !STRINGP (it->string);
6993 ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
6994 ptrdiff_t bob = (buffer_p ? BEGV : 0);
6995
6996 eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
6997
6998
6999
7000
7001 if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
7002 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
7003
7004 while (it->bidi_it.charpos >= bob
7005 && it->prev_stop <= it->bidi_it.charpos
7006 && it->bidi_it.charpos < CHARPOS (it->position)
7007 && it->bidi_it.charpos < eob)
7008 bidi_move_to_visually_next (&it->bidi_it);
7009
7010
7011 if (it->bidi_it.charpos > CHARPOS (it->position))
7012 it->prev_stop = CHARPOS (it->position);
7013
7014
7015 if (it->bidi_it.charpos != CHARPOS (it->position))
7016 SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
7017 if (buffer_p)
7018 it->current.pos = it->position;
7019 else
7020 it->current.string_pos = it->position;
7021 }
7022
7023
7024
7025
7026
7027 static void
7028 restore_face_box_flags (struct it *it, int prev_face_id)
7029 {
7030 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
7031
7032 if (face)
7033 {
7034 struct face *prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
7035
7036 if (!(it->start_of_box_run_p && prev_face && prev_face->box))
7037 it->start_of_box_run_p = (face->box != FACE_NO_BOX
7038 && (prev_face == NULL
7039 || prev_face->box == FACE_NO_BOX));
7040 it->face_box_p = face->box != FACE_NO_BOX;
7041 }
7042 }
7043
7044
7045
7046
7047
7048
7049
7050 static void
7051 pop_it (struct it *it)
7052 {
7053 struct iterator_stack_entry *p;
7054 bool from_display_prop = it->from_disp_prop_p;
7055 ptrdiff_t prev_pos = IT_CHARPOS (*it);
7056 int prev_face_id = it->face_id;
7057
7058 eassert (it->sp > 0);
7059 --it->sp;
7060 p = it->stack + it->sp;
7061 it->stop_charpos = p->stop_charpos;
7062 it->prev_stop = p->prev_stop;
7063 it->base_level_stop = p->base_level_stop;
7064 it->cmp_it = p->cmp_it;
7065 it->face_id = p->face_id;
7066 it->current = p->current;
7067 it->position = p->position;
7068 it->string = p->string;
7069 it->from_overlay = p->from_overlay;
7070 if (NILP (it->string))
7071 SET_TEXT_POS (it->current.string_pos, -1, -1);
7072 it->method = p->method;
7073 switch (it->method)
7074 {
7075 case GET_FROM_IMAGE:
7076 it->image_id = p->u.image.image_id;
7077 it->object = p->u.image.object;
7078 it->slice = p->u.image.slice;
7079 break;
7080 case GET_FROM_XWIDGET:
7081 it->object = p->u.xwidget.object;
7082 break;
7083 case GET_FROM_STRETCH:
7084 it->object = p->u.stretch.object;
7085 break;
7086 case GET_FROM_BUFFER:
7087 {
7088 restore_face_box_flags (it, prev_face_id);
7089 it->object = it->w->contents;
7090 }
7091 break;
7092 case GET_FROM_STRING:
7093 {
7094 restore_face_box_flags (it, prev_face_id);
7095 it->object = it->string;
7096 }
7097 break;
7098 case GET_FROM_DISPLAY_VECTOR:
7099 if (it->s)
7100 it->method = GET_FROM_C_STRING;
7101 else if (STRINGP (it->string))
7102 it->method = GET_FROM_STRING;
7103 else
7104 {
7105 it->method = GET_FROM_BUFFER;
7106 it->object = it->w->contents;
7107 }
7108 break;
7109 case GET_FROM_C_STRING:
7110 break;
7111 default:
7112 emacs_abort ();
7113 }
7114 it->end_charpos = p->end_charpos;
7115 it->string_nchars = p->string_nchars;
7116 it->area = p->area;
7117 it->multibyte_p = p->multibyte_p;
7118 it->avoid_cursor_p = p->avoid_cursor_p;
7119 it->space_width = p->space_width;
7120 it->font_height = p->font_height;
7121 it->voffset = p->voffset;
7122 it->string_from_display_prop_p = p->string_from_display_prop_p;
7123 it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
7124 it->line_wrap = p->line_wrap;
7125 it->bidi_p = p->bidi_p;
7126 it->paragraph_embedding = p->paragraph_embedding;
7127 it->from_disp_prop_p = p->from_disp_prop_p;
7128 if (it->bidi_p)
7129 {
7130 bidi_pop_it (&it->bidi_it);
7131
7132
7133
7134
7135
7136
7137
7138 if (from_display_prop
7139 && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
7140 iterate_out_of_display_property (it);
7141
7142 eassert ((BUFFERP (it->object)
7143 && IT_CHARPOS (*it) == it->bidi_it.charpos
7144 && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
7145 || (STRINGP (it->object)
7146 && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
7147 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
7148 || (CONSP (it->object) && it->method == GET_FROM_STRETCH)
7149
7150
7151
7152
7153
7154
7155 || it->sp > 0);
7156 }
7157
7158
7159
7160 if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
7161 it->ignore_overlay_strings_at_pos_p = false;
7162 }
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172 static void
7173 back_to_previous_line_start (struct it *it)
7174 {
7175 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
7176
7177 dec_both (&cp, &bp);
7178 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7179 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
7180 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
7181 }
7182
7183
7184
7185
7186
7187 static bool
7188 strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7189 {
7190 struct itree_node *node;
7191
7192 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7193 {
7194 Lisp_Object overlay = node->data;
7195 eassert (OVERLAYP (overlay));
7196
7197
7198 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7199 if (WINDOWP (window) && XWINDOW (window) != w)
7200 continue;
7201
7202 ptrdiff_t ostart = node->begin;
7203 ptrdiff_t oend = node->end;
7204
7205
7206 if (!((startpos < oend && ostart < endpos)
7207 || (ostart == oend
7208 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7209 continue;
7210
7211 Lisp_Object str;
7212 str = Foverlay_get (overlay, Qbefore_string);
7213 if (STRINGP (str) && SCHARS (str)
7214 && memchr (SDATA (str), '\n', SBYTES (str)))
7215 return true;
7216 str = Foverlay_get (overlay, Qafter_string);
7217 if (STRINGP (str) && SCHARS (str)
7218 && memchr (SDATA (str), '\n', SBYTES (str)))
7219 return true;
7220 }
7221
7222
7223 Lisp_Object cpos = make_fixnum (startpos);
7224 Lisp_Object limpos = make_fixnum (endpos);
7225
7226 while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos),
7227 !(NILP (cpos) || XFIXNAT (cpos) >= endpos)))
7228 {
7229 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
7230 Lisp_Object string = string_from_display_spec (spec);
7231 if (STRINGP (string)
7232 && memchr (SDATA (string), '\n', SBYTES (string)))
7233 return true;
7234 }
7235
7236 return false;
7237 }
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261 static bool
7262 forward_to_next_line_start (struct it *it, bool *skipped_p,
7263 struct bidi_it *bidi_it_prev)
7264 {
7265 ptrdiff_t old_selective;
7266 bool newline_found_p = false;
7267 int n;
7268 const int MAX_NEWLINE_DISTANCE = 500;
7269
7270
7271
7272 if (it->what == IT_CHARACTER
7273 && it->c == '\n'
7274 && CHARPOS (it->position) == IT_CHARPOS (*it))
7275 {
7276 if (it->bidi_p && bidi_it_prev)
7277 *bidi_it_prev = it->bidi_it;
7278 set_iterator_to_next (it, false);
7279 it->c = 0;
7280 return true;
7281 }
7282
7283
7284
7285
7286
7287 old_selective = it->selective;
7288 it->selective = 0;
7289
7290
7291
7292
7293 for (n = 0;
7294 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
7295 n += !STRINGP (it->string))
7296 {
7297 if (!get_next_display_element (it))
7298 return false;
7299 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
7300 if (newline_found_p && it->bidi_p && bidi_it_prev)
7301 *bidi_it_prev = it->bidi_it;
7302 set_iterator_to_next (it, false);
7303 }
7304
7305
7306
7307 if (!newline_found_p)
7308 {
7309 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
7310 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
7311 1, &bytepos);
7312 eassert (!STRINGP (it->string));
7313
7314
7315
7316
7317 bool no_strings_with_newlines = it->stop_charpos >= limit;
7318
7319 if (!no_strings_with_newlines)
7320 {
7321 if (!(current_buffer->long_line_optimizations_p
7322 && it->line_wrap == TRUNCATE))
7323 {
7324
7325
7326 Lisp_Object pos =
7327 Fnext_single_property_change (make_fixnum (start),
7328 Qdisplay, Qnil,
7329 make_fixnum (limit));
7330 no_strings_with_newlines =
7331 (NILP (pos) || XFIXNAT (pos) == limit)
7332 && next_overlay_change (start) == ZV;
7333 }
7334 else
7335 {
7336
7337
7338
7339
7340 no_strings_with_newlines =
7341 !strings_with_newlines (start, limit, it->w);
7342 }
7343 }
7344
7345
7346
7347
7348 if (no_strings_with_newlines)
7349 {
7350 if (!it->bidi_p || !bidi_it_prev)
7351 {
7352
7353 IT_CHARPOS (*it) = limit;
7354 IT_BYTEPOS (*it) = bytepos;
7355 }
7356 else
7357 {
7358
7359
7360
7361 struct bidi_it bprev;
7362
7363
7364
7365
7366 if (it->bidi_it.disp_pos < limit)
7367 {
7368 it->bidi_it.disp_pos = limit;
7369 it->bidi_it.disp_prop = 0;
7370 }
7371 do {
7372 bprev = it->bidi_it;
7373 bidi_move_to_visually_next (&it->bidi_it);
7374 } while (it->bidi_it.charpos != limit);
7375 IT_CHARPOS (*it) = limit;
7376 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7377 if (bidi_it_prev)
7378 *bidi_it_prev = bprev;
7379 }
7380 *skipped_p = newline_found_p = true;
7381 }
7382 else
7383 {
7384
7385 while (!newline_found_p)
7386 {
7387 if (!get_next_display_element (it))
7388 break;
7389 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
7390 if (newline_found_p && it->bidi_p && bidi_it_prev)
7391 *bidi_it_prev = it->bidi_it;
7392 set_iterator_to_next (it, false);
7393 }
7394 }
7395 }
7396
7397 it->selective = old_selective;
7398 return newline_found_p;
7399 }
7400
7401
7402
7403
7404
7405
7406
7407 static void
7408 back_to_previous_visible_line_start (struct it *it)
7409 {
7410 while (IT_CHARPOS (*it) > BEGV)
7411 {
7412 back_to_previous_line_start (it);
7413
7414 if (IT_CHARPOS (*it) <= BEGV)
7415 break;
7416
7417
7418
7419 if (it->selective > 0
7420 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7421 it->selective))
7422 continue;
7423
7424
7425 {
7426 Lisp_Object prop;
7427 prop = Fget_char_property (make_fixnum (IT_CHARPOS (*it) - 1),
7428 Qinvisible, it->window);
7429 if (TEXT_PROP_MEANS_INVISIBLE (prop) != 0)
7430 continue;
7431 }
7432
7433 if (IT_CHARPOS (*it) <= BEGV)
7434 break;
7435
7436 {
7437 struct it it2;
7438 void *it2data = NULL;
7439 ptrdiff_t pos;
7440 ptrdiff_t beg, end;
7441 Lisp_Object val, overlay;
7442
7443 SAVE_IT (it2, *it, it2data);
7444
7445
7446 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
7447 && beg < IT_CHARPOS (*it))
7448 goto replaced;
7449
7450
7451
7452 pos = --IT_CHARPOS (it2);
7453 --IT_BYTEPOS (it2);
7454 it2.sp = 0;
7455 bidi_unshelve_cache (NULL, false);
7456 it2.string_from_display_prop_p = false;
7457 it2.from_disp_prop_p = false;
7458 if (handle_display_prop (&it2) == HANDLED_RETURN
7459 && !NILP (val = get_char_property_and_overlay
7460 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7461 && (OVERLAYP (overlay)
7462 ? (beg = OVERLAY_START (overlay))
7463 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7464 {
7465 RESTORE_IT (it, it, it2data);
7466 goto replaced;
7467 }
7468
7469
7470 RESTORE_IT (it, it, it2data);
7471 break;
7472
7473 replaced:
7474 if (beg < BEGV)
7475 beg = BEGV;
7476 IT_CHARPOS (*it) = beg;
7477 IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
7478 }
7479 }
7480
7481 it->continuation_lines_width = 0;
7482
7483 eassert (IT_CHARPOS (*it) >= BEGV);
7484 eassert (it->medium_narrowing_begv > 0
7485 || IT_CHARPOS (*it) == BEGV
7486 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7487 CHECK_IT (it);
7488 }
7489
7490
7491
7492
7493
7494
7495
7496 void
7497 reseat_at_previous_visible_line_start (struct it *it)
7498 {
7499 back_to_previous_visible_line_start (it);
7500 reseat (it, it->current.pos, true);
7501 CHECK_IT (it);
7502 }
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512 static void
7513 reseat_at_next_visible_line_start (struct it *it, bool on_newline_p)
7514 {
7515 bool skipped_p = false;
7516 struct bidi_it bidi_it_prev;
7517 bool newline_found_p
7518 = forward_to_next_line_start (it, &skipped_p,
7519 on_newline_p ? &bidi_it_prev : NULL);
7520
7521
7522
7523 if (it->selective > 0)
7524 while (IT_CHARPOS (*it) < ZV
7525 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7526 it->selective))
7527 {
7528 eassert (IT_BYTEPOS (*it) == BEGV
7529 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7530 newline_found_p =
7531 forward_to_next_line_start (it, &skipped_p,
7532 on_newline_p ? &bidi_it_prev : NULL);
7533 }
7534
7535
7536 if (on_newline_p && newline_found_p)
7537 {
7538 if (STRINGP (it->string))
7539 {
7540 if (IT_STRING_CHARPOS (*it) > 0)
7541 {
7542 if (!it->bidi_p)
7543 {
7544 --IT_STRING_CHARPOS (*it);
7545 --IT_STRING_BYTEPOS (*it);
7546 }
7547 else
7548 {
7549
7550
7551
7552 it->bidi_it = bidi_it_prev;
7553 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
7554 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
7555 }
7556 }
7557 }
7558 else if (IT_CHARPOS (*it) > BEGV)
7559 {
7560 if (!it->bidi_p)
7561 {
7562 --IT_CHARPOS (*it);
7563 --IT_BYTEPOS (*it);
7564 }
7565 else
7566 {
7567
7568
7569 it->bidi_it = bidi_it_prev;
7570 IT_CHARPOS (*it) = it->bidi_it.charpos;
7571 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7572 }
7573 reseat (it, it->current.pos, false);
7574 }
7575 }
7576 else if (skipped_p)
7577 reseat (it, it->current.pos, false);
7578
7579 CHECK_IT (it);
7580 }
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593 static void
7594 reseat (struct it *it, struct text_pos pos, bool force_p)
7595 {
7596 ptrdiff_t original_pos = IT_CHARPOS (*it);
7597
7598 reseat_1 (it, pos, false);
7599
7600 if (current_buffer->long_line_optimizations_p)
7601 {
7602 if (!it->medium_narrowing_begv)
7603 {
7604 it->medium_narrowing_begv
7605 = get_medium_narrowing_begv (it->w, window_point (it->w));
7606 it->medium_narrowing_zv
7607 = get_medium_narrowing_zv (it->w, window_point (it->w));
7608 it->large_narrowing_begv
7609 = get_large_narrowing_begv (window_point (it->w));
7610 it->large_narrowing_zv
7611 = get_large_narrowing_zv (window_point (it->w));
7612 }
7613 else if ((pos.charpos < it->medium_narrowing_begv
7614 || pos.charpos > it->medium_narrowing_zv)
7615 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7616 {
7617 it->medium_narrowing_begv
7618 = get_medium_narrowing_begv (it->w, pos.charpos);
7619 it->medium_narrowing_zv
7620 = get_medium_narrowing_zv (it->w, pos.charpos);
7621 it->large_narrowing_begv
7622 = get_large_narrowing_begv (window_point (it->w));
7623 it->large_narrowing_zv
7624 = get_large_narrowing_zv (window_point (it->w));
7625 }
7626 }
7627
7628
7629
7630 if (force_p
7631 || CHARPOS (pos) > it->stop_charpos
7632 || CHARPOS (pos) < original_pos)
7633 {
7634 if (it->bidi_p)
7635 {
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646 if (CHARPOS (pos) != it->prev_stop)
7647 it->prev_stop = CHARPOS (pos);
7648 if (CHARPOS (pos) < it->base_level_stop)
7649 it->base_level_stop = 0;
7650 handle_stop (it);
7651 }
7652 else
7653 {
7654 handle_stop (it);
7655 it->prev_stop = it->base_level_stop = 0;
7656 }
7657
7658 }
7659
7660 CHECK_IT (it);
7661 }
7662
7663
7664
7665
7666
7667 static void
7668 reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7669 {
7670
7671 eassert (it->s == NULL);
7672
7673
7674 eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
7675
7676 it->current.pos = it->position = pos;
7677 it->end_charpos = ZV;
7678 it->dpvec = NULL;
7679 it->current.dpvec_index = -1;
7680 it->current.overlay_string_index = -1;
7681 IT_STRING_CHARPOS (*it) = -1;
7682 IT_STRING_BYTEPOS (*it) = -1;
7683 it->string = Qnil;
7684 it->method = GET_FROM_BUFFER;
7685 it->object = it->w->contents;
7686 it->area = TEXT_AREA;
7687 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
7688 it->sp = 0;
7689 it->string_from_display_prop_p = false;
7690 it->string_from_prefix_prop_p = false;
7691
7692 it->from_disp_prop_p = false;
7693 it->face_before_selective_p = false;
7694 if (it->bidi_p)
7695 {
7696 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7697 &it->bidi_it);
7698 bidi_unshelve_cache (NULL, false);
7699 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7700 it->bidi_it.string.s = NULL;
7701 it->bidi_it.string.lstring = Qnil;
7702 it->bidi_it.string.bufpos = 0;
7703 it->bidi_it.string.from_disp_str = false;
7704 it->bidi_it.string.unibyte = false;
7705 it->bidi_it.w = it->w;
7706 }
7707
7708 if (set_stop_p)
7709 {
7710 it->stop_charpos = CHARPOS (pos);
7711 it->base_level_stop = CHARPOS (pos);
7712 }
7713
7714 it->cmp_it.id = -1;
7715 it->min_width_property = Qnil;
7716 }
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737 static void
7738 reseat_to_string (struct it *it, const char *s, Lisp_Object string,
7739 ptrdiff_t charpos, ptrdiff_t precision, int field_width,
7740 int multibyte)
7741 {
7742
7743 it->stop_charpos = -1;
7744
7745
7746 memset (&it->current, 0, sizeof it->current);
7747 it->current.overlay_string_index = -1;
7748 it->current.dpvec_index = -1;
7749 eassert (charpos >= 0);
7750
7751
7752
7753 if (multibyte >= 0)
7754 it->multibyte_p = multibyte > 0;
7755
7756
7757
7758
7759
7760 it->bidi_p =
7761 !redisplay__inhibit_bidi
7762 && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
7763
7764 if (s == NULL)
7765 {
7766 eassert (STRINGP (string));
7767 it->string = string;
7768 it->s = NULL;
7769 it->end_charpos = it->string_nchars = SCHARS (string);
7770 it->method = GET_FROM_STRING;
7771 it->current.string_pos = string_pos (charpos, string);
7772
7773 if (it->bidi_p)
7774 {
7775 it->bidi_it.string.lstring = string;
7776 it->bidi_it.string.s = NULL;
7777 it->bidi_it.string.schars = it->end_charpos;
7778 it->bidi_it.string.bufpos = 0;
7779 it->bidi_it.string.from_disp_str = false;
7780 it->bidi_it.string.unibyte = !it->multibyte_p;
7781 it->bidi_it.w = it->w;
7782 bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
7783 FRAME_WINDOW_P (it->f), &it->bidi_it);
7784 }
7785 }
7786 else
7787 {
7788 it->s = (const unsigned char *) s;
7789 it->string = Qnil;
7790
7791
7792
7793 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
7794 if (it->multibyte_p)
7795 {
7796 it->current.pos = c_string_pos (charpos, s, true);
7797 it->end_charpos = it->string_nchars = number_of_chars (s, true);
7798 }
7799 else
7800 {
7801 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
7802 it->end_charpos = it->string_nchars = strlen (s);
7803 }
7804
7805 if (it->bidi_p)
7806 {
7807 it->bidi_it.string.lstring = Qnil;
7808 it->bidi_it.string.s = (const unsigned char *) s;
7809 it->bidi_it.string.schars = it->end_charpos;
7810 it->bidi_it.string.bufpos = 0;
7811 it->bidi_it.string.from_disp_str = false;
7812 it->bidi_it.string.unibyte = !it->multibyte_p;
7813 it->bidi_it.w = it->w;
7814 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7815 &it->bidi_it);
7816 }
7817 it->method = GET_FROM_C_STRING;
7818 }
7819
7820
7821
7822 if (precision > 0 && it->end_charpos - charpos > precision)
7823 {
7824 it->end_charpos = it->string_nchars = charpos + precision;
7825 if (it->bidi_p)
7826 it->bidi_it.string.schars = it->end_charpos;
7827 }
7828
7829
7830
7831
7832
7833 if (field_width < 0)
7834 field_width = DISP_INFINITY;
7835
7836
7837
7838 if (field_width > it->end_charpos - charpos)
7839 it->end_charpos = charpos + field_width;
7840
7841
7842 if (DISP_TABLE_P (Vstandard_display_table))
7843 it->dp = XCHAR_TABLE (Vstandard_display_table);
7844
7845 it->stop_charpos = charpos;
7846 it->prev_stop = charpos;
7847 it->base_level_stop = 0;
7848 if (it->bidi_p)
7849 {
7850 it->bidi_it.first_elt = true;
7851 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7852 it->bidi_it.disp_pos = -1;
7853 }
7854 if (s == NULL && it->multibyte_p)
7855 {
7856 ptrdiff_t endpos = SCHARS (it->string);
7857 if (endpos > it->end_charpos)
7858 endpos = it->end_charpos;
7859 composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
7860 it->string, true);
7861 }
7862 CHECK_IT (it);
7863 }
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873 typedef bool (*next_element_function) (struct it *);
7874
7875 static next_element_function const get_next_element[NUM_IT_METHODS] =
7876 {
7877 next_element_from_buffer,
7878 next_element_from_display_vector,
7879 next_element_from_string,
7880 next_element_from_c_string,
7881 next_element_from_image,
7882 next_element_from_stretch,
7883 next_element_from_xwidget,
7884 };
7885
7886 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897 #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS) \
7898 ((IT)->cmp_it.id >= 0 \
7899 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
7900 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
7901 END_CHARPOS, (IT)->w, \
7902 (IT)->bidi_p \
7903 ? (IT)->bidi_it.resolved_level \
7904 : -1, \
7905 FACE_FROM_ID_OR_NULL ((IT)->f, \
7906 (IT)->face_id), \
7907 (IT)->string)))
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917 Lisp_Object
7918 lookup_glyphless_char_display (int c, struct it *it)
7919 {
7920 Lisp_Object glyphless_method = Qnil;
7921
7922 if (CHAR_TABLE_P (Vglyphless_char_display)
7923 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
7924 {
7925 if (c >= 0)
7926 glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
7927 else
7928 glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
7929
7930 if (CONSP (glyphless_method))
7931 glyphless_method = FRAME_WINDOW_P (it->f)
7932 ? XCAR (glyphless_method)
7933 : XCDR (glyphless_method);
7934 }
7935
7936 retry:
7937 if (NILP (glyphless_method))
7938 {
7939 if (c >= 0)
7940
7941 return Qnil;
7942
7943 glyphless_method = Qempty_box;
7944 }
7945 if (EQ (glyphless_method, Qzero_width))
7946 {
7947 if (c >= 0)
7948 return glyphless_method;
7949
7950 glyphless_method = Qempty_box;
7951 }
7952 if (EQ (glyphless_method, Qthin_space))
7953 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
7954 else if (EQ (glyphless_method, Qempty_box))
7955 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
7956 else if (EQ (glyphless_method, Qhex_code))
7957 it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
7958 else if (STRINGP (glyphless_method))
7959 it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
7960 else
7961 {
7962
7963 glyphless_method = Qnil;
7964 goto retry;
7965 }
7966 it->what = IT_GLYPHLESS;
7967 return glyphless_method;
7968 }
7969
7970
7971
7972 static struct frame *last_escape_glyph_frame = NULL;
7973 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
7974 static int last_escape_glyph_merged_face_id = 0;
7975
7976 static int
7977 merge_escape_glyph_face (struct it *it)
7978 {
7979 int face_id;
7980
7981 if (it->f == last_escape_glyph_frame
7982 && it->face_id == last_escape_glyph_face_id)
7983 face_id = last_escape_glyph_merged_face_id;
7984 else
7985 {
7986
7987 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
7988 last_escape_glyph_frame = it->f;
7989 last_escape_glyph_face_id = it->face_id;
7990 last_escape_glyph_merged_face_id = face_id;
7991 }
7992 return face_id;
7993 }
7994
7995
7996
7997 static struct frame *last_glyphless_glyph_frame = NULL;
7998 static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
7999 static int last_glyphless_glyph_merged_face_id = 0;
8000
8001 int
8002 merge_glyphless_glyph_face (struct it *it)
8003 {
8004 int face_id;
8005
8006 if (it->f == last_glyphless_glyph_frame
8007 && it->face_id == last_glyphless_glyph_face_id)
8008 face_id = last_glyphless_glyph_merged_face_id;
8009 else
8010 {
8011
8012 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
8013 last_glyphless_glyph_frame = it->f;
8014 last_glyphless_glyph_face_id = it->face_id;
8015 last_glyphless_glyph_merged_face_id = face_id;
8016 }
8017 return face_id;
8018 }
8019
8020
8021
8022
8023 void
8024 forget_escape_and_glyphless_faces (void)
8025 {
8026 last_escape_glyph_frame = NULL;
8027 last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8028 last_glyphless_glyph_frame = NULL;
8029 last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8030 }
8031
8032
8033
8034
8035
8036 static bool
8037 get_next_display_element (struct it *it)
8038 {
8039
8040
8041
8042
8043 bool success_p;
8044
8045 get_next:
8046 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
8047
8048 if (it->what == IT_CHARACTER)
8049 {
8050
8051
8052
8053
8054
8055 if (it->bidi_p && it->bidi_it.type == STRONG_R
8056 && !inhibit_bidi_mirroring)
8057 it->c = bidi_mirror_char (it->c);
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067 if (success_p && it->dpvec == NULL)
8068 {
8069 Lisp_Object dv;
8070 struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
8071 bool nonascii_space_p = false;
8072 bool nonascii_hyphen_p = false;
8073 int c = it->c;
8074
8075 if (! it->multibyte_p && ! ASCII_CHAR_P (c))
8076 {
8077 eassert (SINGLE_BYTE_CHAR_P (c));
8078 if (unibyte_display_via_language_environment)
8079 {
8080 c = DECODE_CHAR (unibyte, c);
8081 if (c < 0)
8082 c = BYTE8_TO_CHAR (it->c);
8083 }
8084 else
8085 c = BYTE8_TO_CHAR (it->c);
8086 }
8087
8088 if (it->dp
8089 && (dv = DISP_CHAR_VECTOR (it->dp, c),
8090 VECTORP (dv)))
8091 {
8092 struct Lisp_Vector *v = XVECTOR (dv);
8093
8094
8095
8096
8097 if (v->header.size)
8098 {
8099 it->dpvec_char_len = it->len;
8100 it->dpvec = v->contents;
8101 it->dpend = v->contents + v->header.size;
8102 it->current.dpvec_index = 0;
8103 it->dpvec_face_id = -1;
8104 it->saved_face_id = it->face_id;
8105 it->method = GET_FROM_DISPLAY_VECTOR;
8106 it->ellipsis_p = false;
8107 }
8108 else
8109 {
8110 set_iterator_to_next (it, false);
8111 }
8112 goto get_next;
8113 }
8114
8115 if (! NILP (lookup_glyphless_char_display (c, it)))
8116 {
8117 if (it->what == IT_GLYPHLESS)
8118 goto done;
8119
8120 set_iterator_to_next (it, false);
8121 goto get_next;
8122 }
8123
8124
8125
8126 if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
8127 {
8128 if (blankp (c))
8129 nonascii_space_p = true;
8130 else if (c == SOFT_HYPHEN || c == HYPHEN
8131 || c == NON_BREAKING_HYPHEN)
8132 nonascii_hyphen_p = true;
8133 }
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146 if (((c < ' ' || c == 127)
8147 ? (it->area != TEXT_AREA
8148
8149 || (c != '\t'
8150 && it->glyph_row
8151 && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
8152 || (c != '\n' && c != '\t'))
8153 : (nonascii_space_p
8154 || nonascii_hyphen_p
8155 || CHAR_BYTE8_P (c)
8156 || ! CHAR_PRINTABLE_P (c))))
8157 {
8158
8159
8160
8161
8162
8163
8164 Lisp_Object gc;
8165 int ctl_len;
8166 int face_id;
8167 int lface_id = 0;
8168 int escape_glyph;
8169
8170
8171
8172 if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
8173 {
8174 int g;
8175
8176 g = '^';
8177
8178 if (it->dp
8179 && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8180 {
8181 g = GLYPH_CODE_CHAR (gc);
8182 lface_id = GLYPH_CODE_FACE (gc);
8183 }
8184
8185 face_id = (lface_id
8186 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8187 : merge_escape_glyph_face (it));
8188
8189 XSETINT (it->ctl_chars[0], g);
8190 XSETINT (it->ctl_chars[1], c ^ 0100);
8191 ctl_len = 2;
8192 goto display_control;
8193 }
8194
8195
8196
8197
8198 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
8199 {
8200
8201 face_id = merge_faces (it->w, Qnobreak_space, 0,
8202 it->face_id);
8203 XSETINT (it->ctl_chars[0],
8204 nobreak_char_ascii_display ? ' ' : it->c);
8205 ctl_len = 1;
8206 goto display_control;
8207 }
8208
8209
8210
8211
8212 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
8213 {
8214
8215 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
8216 it->face_id);
8217 XSETINT (it->ctl_chars[0],
8218 nobreak_char_ascii_display ? '-' : it->c);
8219 ctl_len = 1;
8220 goto display_control;
8221 }
8222
8223
8224
8225
8226 escape_glyph = '\\';
8227
8228 if (it->dp
8229 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8230 {
8231 escape_glyph = GLYPH_CODE_CHAR (gc);
8232 lface_id = GLYPH_CODE_FACE (gc);
8233 }
8234
8235 face_id = (lface_id
8236 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8237 : merge_escape_glyph_face (it));
8238
8239
8240
8241 if (nonascii_space_p || nonascii_hyphen_p)
8242 {
8243 XSETINT (it->ctl_chars[0], escape_glyph);
8244 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
8245 ctl_len = 2;
8246 goto display_control;
8247 }
8248
8249 {
8250 char str[10];
8251 int len, i;
8252
8253 if (CHAR_BYTE8_P (c))
8254
8255 c = CHAR_TO_BYTE8 (c);
8256 const char *format_string = display_raw_bytes_as_hex
8257 ? "x%02x"
8258 : "%03o";
8259 len = sprintf (str, format_string, c + 0u);
8260
8261 XSETINT (it->ctl_chars[0], escape_glyph);
8262 for (i = 0; i < len; i++)
8263 XSETINT (it->ctl_chars[i + 1], str[i]);
8264 ctl_len = len + 1;
8265 }
8266
8267 display_control:
8268
8269 it->dpvec_char_len = it->len;
8270 it->dpvec = it->ctl_chars;
8271 it->dpend = it->dpvec + ctl_len;
8272 it->current.dpvec_index = 0;
8273 it->dpvec_face_id = face_id;
8274 it->saved_face_id = it->face_id;
8275 it->method = GET_FROM_DISPLAY_VECTOR;
8276 it->ellipsis_p = false;
8277 goto get_next;
8278 }
8279 it->char_to_display = c;
8280 }
8281 else if (success_p)
8282 {
8283 it->char_to_display = it->c;
8284 }
8285 }
8286
8287 #ifdef HAVE_WINDOW_SYSTEM
8288
8289
8290 if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
8291 && it->multibyte_p
8292 && success_p
8293 && FRAME_WINDOW_P (it->f))
8294 {
8295 struct face *face = FACE_FROM_ID (it->f, it->face_id);
8296
8297 if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8298 {
8299
8300 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8301
8302 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8303 }
8304 else
8305 {
8306 ptrdiff_t pos = (it->s ? -1
8307 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8308 : IT_CHARPOS (*it));
8309 int c;
8310
8311 if (it->what == IT_CHARACTER)
8312 c = it->char_to_display;
8313 else
8314 {
8315 struct composition *cmp = composition_table[it->cmp_it.id];
8316 int i;
8317
8318 c = ' ';
8319 for (i = 0; i < cmp->glyph_len; i++)
8320
8321
8322 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8323 break;
8324 }
8325 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8326 }
8327 }
8328 #endif
8329
8330 done:
8331
8332
8333 if (it->face_box_p
8334 && it->s == NULL)
8335 {
8336 if (it->method == GET_FROM_STRING && it->sp)
8337 {
8338 int face_id = underlying_face_id (it);
8339 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8340
8341 if (face)
8342 {
8343 if (face->box == FACE_NO_BOX)
8344 {
8345
8346
8347 int string_face_id = face_after_it_pos (it);
8348 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8349 it->end_of_box_run_p = true;
8350 }
8351
8352
8353
8354 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8355
8356
8357
8358 || (it->what == IT_COMPOSITION
8359 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8360 >= SCHARS (it->string))))
8361
8362
8363 && ((it->current.overlay_string_index >= 0
8364 && (it->current.overlay_string_index
8365 == it->n_overlay_strings - 1))
8366
8367 || it->from_disp_prop_p))
8368 {
8369 ptrdiff_t ignore;
8370 int next_face_id;
8371 bool text_from_string = false;
8372
8373
8374 struct text_pos pos = it->current.pos;
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386 if (it->from_disp_prop_p)
8387 {
8388 int stackp = it->sp - 1;
8389
8390
8391 while (stackp >= 0
8392 && STRINGP ((it->stack + stackp)->string))
8393 stackp--;
8394 if (stackp < 0)
8395 {
8396
8397
8398
8399
8400
8401
8402 text_from_string = true;
8403 pos = it->stack[it->sp - 1].position;
8404 }
8405 else
8406 pos = (it->stack + stackp)->position;
8407 }
8408 else
8409 INC_TEXT_POS (pos, it->multibyte_p);
8410
8411 if (text_from_string)
8412 {
8413 Lisp_Object base_string = it->stack[it->sp - 1].string;
8414
8415 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8416 it->end_of_box_run_p = true;
8417 else
8418 {
8419 next_face_id
8420 = face_at_string_position (it->w, base_string,
8421 CHARPOS (pos), 0,
8422 &ignore, face_id,
8423 false, 0);
8424 if (FACE_FROM_ID (it->f, next_face_id)->box
8425 == FACE_NO_BOX)
8426 it->end_of_box_run_p = true;
8427 }
8428 }
8429 else if (CHARPOS (pos) >= ZV)
8430 it->end_of_box_run_p = true;
8431 else
8432 {
8433 next_face_id =
8434 face_at_buffer_position (it->w, CHARPOS (pos),
8435 &ignore,
8436 CHARPOS (pos)
8437 + TEXT_PROP_DISTANCE_LIMIT,
8438 false, -1, 0);
8439 if (FACE_FROM_ID (it->f, next_face_id)->box
8440 == FACE_NO_BOX)
8441 it->end_of_box_run_p = true;
8442 }
8443 }
8444 }
8445 }
8446
8447
8448 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8449 {
8450 int face_id = face_after_it_pos (it);
8451 if (face_id != it->face_id
8452 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8453 it->end_of_box_run_p = true;
8454 }
8455 }
8456
8457
8458
8459
8460
8461 if (!success_p && it->sp > 0)
8462 {
8463 set_iterator_to_next (it, false);
8464 success_p = get_next_display_element (it);
8465 }
8466
8467
8468 return success_p;
8469 }
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487 void
8488 set_iterator_to_next (struct it *it, bool reseat_p)
8489 {
8490
8491 if (max_redisplay_ticks > 0)
8492 update_redisplay_ticks (1, it->w);
8493
8494 switch (it->method)
8495 {
8496 case GET_FROM_BUFFER:
8497
8498
8499
8500 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8501 reseat_at_next_visible_line_start (it, false);
8502 else if (it->cmp_it.id >= 0)
8503 {
8504
8505 if (! it->bidi_p)
8506 {
8507 IT_CHARPOS (*it) += it->cmp_it.nchars;
8508 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8509 }
8510 else
8511 {
8512 int i;
8513
8514
8515
8516
8517 for (i = 0; i < it->cmp_it.nchars; i++)
8518 bidi_move_to_visually_next (&it->bidi_it);
8519 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8520 IT_CHARPOS (*it) = it->bidi_it.charpos;
8521 }
8522
8523 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8524 && it->cmp_it.to < it->cmp_it.nglyphs)
8525 {
8526
8527
8528 it->cmp_it.from = it->cmp_it.to;
8529 }
8530 else if ((it->bidi_p && it->cmp_it.reversed_p)
8531 && it->cmp_it.from > 0)
8532 {
8533
8534
8535 it->cmp_it.to = it->cmp_it.from;
8536 }
8537 else
8538 {
8539
8540
8541 ptrdiff_t stop = it->end_charpos;
8542
8543 if (it->bidi_it.scan_dir < 0)
8544
8545
8546 stop = -1;
8547 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8548 IT_BYTEPOS (*it), stop, Qnil, true);
8549 }
8550 }
8551 else
8552 {
8553 eassert (it->len != 0);
8554
8555 if (!it->bidi_p)
8556 {
8557 IT_BYTEPOS (*it) += it->len;
8558 IT_CHARPOS (*it) += 1;
8559 }
8560 else
8561 {
8562 int prev_scan_dir = it->bidi_it.scan_dir;
8563
8564
8565 if (it->bidi_it.new_paragraph)
8566 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8567 false);
8568 bidi_move_to_visually_next (&it->bidi_it);
8569 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8570 IT_CHARPOS (*it) = it->bidi_it.charpos;
8571 if (prev_scan_dir != it->bidi_it.scan_dir)
8572 {
8573
8574
8575 ptrdiff_t stop = it->end_charpos;
8576 if (it->bidi_it.scan_dir < 0)
8577 stop = -1;
8578 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8579 IT_BYTEPOS (*it), stop, Qnil,
8580 true);
8581 }
8582 }
8583 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8584 }
8585 break;
8586
8587 case GET_FROM_C_STRING:
8588
8589 if (!it->bidi_p
8590
8591
8592
8593
8594 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8595 {
8596 IT_BYTEPOS (*it) += it->len;
8597 IT_CHARPOS (*it) += 1;
8598 }
8599 else
8600 {
8601 bidi_move_to_visually_next (&it->bidi_it);
8602 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8603 IT_CHARPOS (*it) = it->bidi_it.charpos;
8604 }
8605 break;
8606
8607 case GET_FROM_DISPLAY_VECTOR:
8608
8609
8610
8611
8612 ++it->current.dpvec_index;
8613
8614
8615
8616 it->face_id = it->saved_face_id;
8617
8618 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8619 {
8620 bool recheck_faces = it->ellipsis_p;
8621
8622 if (it->s)
8623 it->method = GET_FROM_C_STRING;
8624 else if (STRINGP (it->string))
8625 it->method = GET_FROM_STRING;
8626 else
8627 {
8628 it->method = GET_FROM_BUFFER;
8629 it->object = it->w->contents;
8630 }
8631
8632 it->dpvec = NULL;
8633 it->current.dpvec_index = -1;
8634
8635
8636 if (it->dpvec_char_len < 0)
8637 reseat_at_next_visible_line_start (it, true);
8638 else if (it->dpvec_char_len > 0)
8639 {
8640 it->len = it->dpvec_char_len;
8641 set_iterator_to_next (it, reseat_p);
8642 }
8643
8644
8645 if (recheck_faces)
8646 {
8647 if (it->method == GET_FROM_STRING)
8648 it->stop_charpos = IT_STRING_CHARPOS (*it);
8649 else
8650 it->stop_charpos = IT_CHARPOS (*it);
8651 }
8652 }
8653 break;
8654
8655 case GET_FROM_STRING:
8656
8657 eassert (it->s == NULL && STRINGP (it->string));
8658
8659
8660
8661
8662
8663 if (it->current.overlay_string_index >= 0)
8664 {
8665
8666
8667
8668 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8669 goto consider_string_end;
8670 }
8671 else
8672 {
8673
8674
8675 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8676 goto consider_string_end;
8677 }
8678 if (it->cmp_it.id >= 0)
8679 {
8680
8681
8682
8683 if (! it->bidi_p)
8684 {
8685 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8686 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8687 }
8688 else
8689 {
8690 int i;
8691
8692 for (i = 0; i < it->cmp_it.nchars; i++)
8693 bidi_move_to_visually_next (&it->bidi_it);
8694 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8695 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8696 }
8697
8698
8699
8700 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8701 && (it->cmp_it.to < it->cmp_it.nglyphs))
8702 {
8703
8704
8705 it->cmp_it.from = it->cmp_it.to;
8706 }
8707 else if ((it->bidi_p && it->cmp_it.reversed_p)
8708 && it->cmp_it.from > 0)
8709 {
8710
8711
8712 it->cmp_it.to = it->cmp_it.from;
8713 }
8714 else
8715 {
8716
8717
8718
8719
8720
8721
8722 ptrdiff_t stop = SCHARS (it->string);
8723
8724 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8725 stop = -1;
8726 else if (it->end_charpos < stop)
8727 {
8728
8729
8730
8731 stop = it->end_charpos;
8732 }
8733 composition_compute_stop_pos (&it->cmp_it,
8734 IT_STRING_CHARPOS (*it),
8735 IT_STRING_BYTEPOS (*it), stop,
8736 it->string, true);
8737 }
8738 }
8739 else
8740 {
8741 if (!it->bidi_p
8742
8743
8744
8745
8746
8747 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8748 {
8749 IT_STRING_BYTEPOS (*it) += it->len;
8750 IT_STRING_CHARPOS (*it) += 1;
8751 }
8752 else
8753 {
8754 int prev_scan_dir = it->bidi_it.scan_dir;
8755
8756 bidi_move_to_visually_next (&it->bidi_it);
8757 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8758 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8759
8760
8761 if (prev_scan_dir != it->bidi_it.scan_dir)
8762 {
8763 ptrdiff_t stop = SCHARS (it->string);
8764
8765 if (it->bidi_it.scan_dir < 0)
8766 stop = -1;
8767 else if (it->end_charpos < stop)
8768 stop = it->end_charpos;
8769
8770 composition_compute_stop_pos (&it->cmp_it,
8771 IT_STRING_CHARPOS (*it),
8772 IT_STRING_BYTEPOS (*it), stop,
8773 it->string, true);
8774 }
8775 }
8776 }
8777
8778 consider_string_end:
8779
8780 if (it->current.overlay_string_index >= 0)
8781 {
8782
8783
8784 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8785 {
8786 it->ellipsis_p = false;
8787 next_overlay_string (it);
8788 if (it->ellipsis_p)
8789 setup_for_ellipsis (it, 0);
8790 }
8791 }
8792 else
8793 {
8794
8795
8796
8797
8798 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8799 && it->sp > 0)
8800 {
8801 pop_it (it);
8802 if (it->method == GET_FROM_STRING)
8803 goto consider_string_end;
8804 }
8805 }
8806 break;
8807
8808 case GET_FROM_IMAGE:
8809 case GET_FROM_STRETCH:
8810 case GET_FROM_XWIDGET:
8811
8812
8813
8814
8815 eassert (it->sp > 0);
8816 pop_it (it);
8817 if (it->method == GET_FROM_STRING)
8818 goto consider_string_end;
8819 break;
8820
8821 default:
8822
8823 emacs_abort ();
8824 }
8825
8826 eassert (it->method != GET_FROM_STRING
8827 || (STRINGP (it->string)
8828 && IT_STRING_CHARPOS (*it) >= 0));
8829 }
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840 static bool
8841 next_element_from_display_vector (struct it *it)
8842 {
8843 Lisp_Object gc;
8844 int prev_face_id = it->face_id;
8845 int next_face_id;
8846
8847
8848 eassert (it->dpvec && it->current.dpvec_index >= 0);
8849
8850 it->face_id = it->saved_face_id;
8851
8852
8853
8854 if (it->dpend - it->dpvec > 0
8855 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8856 {
8857 struct face *this_face, *prev_face, *next_face;
8858
8859 it->c = GLYPH_CODE_CHAR (gc);
8860 it->len = CHAR_BYTES (it->c);
8861
8862
8863
8864
8865 if (it->dpvec_face_id >= 0)
8866 it->face_id = it->dpvec_face_id;
8867 else
8868 {
8869 int lface_id = GLYPH_CODE_FACE (gc);
8870 if (lface_id > 0)
8871 it->face_id = merge_faces (it->w, Qt, lface_id,
8872 it->saved_face_id);
8873 }
8874
8875
8876
8877
8878 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8879 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8880
8881
8882 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8883 && (!prev_face
8884 || prev_face->box == FACE_NO_BOX));
8885
8886
8887
8888
8889 next_face_id = it->saved_face_id;
8890 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8891 {
8892 if (it->dpvec_face_id >= 0)
8893 next_face_id = it->dpvec_face_id;
8894 else
8895 {
8896 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8897 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8898
8899 if (lface_id > 0)
8900 next_face_id = merge_faces (it->w, Qt, lface_id,
8901 it->saved_face_id);
8902 }
8903 }
8904 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8905 if (this_face && this_face->box != FACE_NO_BOX
8906 && (!next_face || next_face->box == FACE_NO_BOX))
8907 it->end_of_box_run_p = true;
8908 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8909 }
8910 else
8911
8912 it->c = ' ', it->len = 1;
8913
8914
8915
8916
8917 it->what = IT_CHARACTER;
8918 return true;
8919 }
8920
8921
8922
8923 static void
8924 get_visually_first_element (struct it *it)
8925 {
8926 bool string_p = STRINGP (it->string) || it->s;
8927 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8928 ptrdiff_t bob;
8929 ptrdiff_t obegv = BEGV;
8930
8931 SET_WITH_NARROWED_BEGV (it, bob,
8932 string_p ? 0 :
8933 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8934 it->medium_narrowing_begv);
8935
8936 if (STRINGP (it->string))
8937 {
8938 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8939 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8940 }
8941 else
8942 {
8943 it->bidi_it.charpos = IT_CHARPOS (*it);
8944 it->bidi_it.bytepos = IT_BYTEPOS (*it);
8945 }
8946
8947 if (it->bidi_it.charpos == eob)
8948 {
8949
8950
8951
8952 it->bidi_it.first_elt = false;
8953 }
8954 else if (it->bidi_it.charpos == bob
8955 || (!string_p
8956 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
8957 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
8958 {
8959
8960
8961 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8962 bidi_move_to_visually_next (&it->bidi_it);
8963 }
8964 else
8965 {
8966 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
8967
8968
8969
8970
8971 if (string_p)
8972 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
8973 else
8974 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
8975 find_newline_no_quit (IT_CHARPOS (*it),
8976 IT_BYTEPOS (*it), -1,
8977 &it->bidi_it.bytepos),
8978 it->medium_narrowing_begv);
8979 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8980 do
8981 {
8982
8983
8984 bidi_move_to_visually_next (&it->bidi_it);
8985 }
8986 while (it->bidi_it.bytepos != orig_bytepos
8987 && it->bidi_it.charpos < eob);
8988 }
8989
8990
8991 if (STRINGP (it->string))
8992 {
8993 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8994 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8995 }
8996 else
8997 {
8998 IT_CHARPOS (*it) = it->bidi_it.charpos;
8999 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
9000 }
9001
9002 if (STRINGP (it->string) || !it->s)
9003 {
9004 ptrdiff_t stop, charpos, bytepos;
9005
9006 if (STRINGP (it->string))
9007 {
9008 eassert (!it->s);
9009 stop = SCHARS (it->string);
9010 if (stop > it->end_charpos)
9011 stop = it->end_charpos;
9012 charpos = IT_STRING_CHARPOS (*it);
9013 bytepos = IT_STRING_BYTEPOS (*it);
9014 }
9015 else
9016 {
9017 stop = it->end_charpos;
9018 charpos = IT_CHARPOS (*it);
9019 bytepos = IT_BYTEPOS (*it);
9020 }
9021 if (it->bidi_it.scan_dir < 0)
9022 stop = -1;
9023 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9024 it->string, true);
9025 }
9026 }
9027
9028
9029
9030
9031
9032
9033 static bool
9034 next_element_from_string (struct it *it)
9035 {
9036 struct text_pos position;
9037
9038 eassert (STRINGP (it->string));
9039 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9040 eassert (IT_STRING_CHARPOS (*it) >= 0);
9041 position = it->current.string_pos;
9042
9043
9044
9045
9046
9047 if (it->bidi_p && it->bidi_it.first_elt)
9048 {
9049 get_visually_first_element (it);
9050 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9051 }
9052
9053
9054 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9055 {
9056 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9057 {
9058 if (!(!it->bidi_p
9059 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9060 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9061 {
9062
9063
9064
9065
9066
9067
9068 handle_stop_backwards (it, it->stop_charpos);
9069 return GET_NEXT_DISPLAY_ELEMENT (it);
9070 }
9071 else
9072 {
9073 if (it->bidi_p)
9074 {
9075
9076
9077 it->prev_stop = it->stop_charpos;
9078
9079
9080
9081 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9082 it->base_level_stop = it->stop_charpos;
9083 }
9084 handle_stop (it);
9085
9086
9087
9088 return GET_NEXT_DISPLAY_ELEMENT (it);
9089 }
9090 }
9091 else if (it->bidi_p
9092
9093
9094
9095 && IT_STRING_CHARPOS (*it) < it->prev_stop
9096
9097
9098
9099
9100 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9101 {
9102
9103
9104
9105
9106 if (it->base_level_stop <= 0
9107 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9108 it->base_level_stop = 0;
9109 handle_stop_backwards (it, it->base_level_stop);
9110 return GET_NEXT_DISPLAY_ELEMENT (it);
9111 }
9112 }
9113
9114 if (it->current.overlay_string_index >= 0)
9115 {
9116
9117
9118
9119 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9120 {
9121 it->what = IT_EOB;
9122 return false;
9123 }
9124 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9125 IT_STRING_BYTEPOS (*it),
9126 it->bidi_it.scan_dir < 0
9127 ? -1
9128 : SCHARS (it->string))
9129 && next_element_from_composition (it))
9130 {
9131 return true;
9132 }
9133 else if (STRING_MULTIBYTE (it->string))
9134 {
9135 const unsigned char *s = (SDATA (it->string)
9136 + IT_STRING_BYTEPOS (*it));
9137 it->c = check_char_and_length (s, &it->len);
9138 }
9139 else
9140 {
9141 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9142 it->len = 1;
9143 }
9144 }
9145 else
9146 {
9147
9148
9149
9150
9151 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9152 {
9153 it->what = IT_EOB;
9154 return false;
9155 }
9156 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9157 {
9158
9159 it->c = ' ', it->len = 1;
9160 CHARPOS (position) = BYTEPOS (position) = -1;
9161 }
9162 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9163 IT_STRING_BYTEPOS (*it),
9164 it->bidi_it.scan_dir < 0
9165 ? -1
9166 : it->string_nchars)
9167 && next_element_from_composition (it))
9168 {
9169 return true;
9170 }
9171 else if (STRING_MULTIBYTE (it->string))
9172 {
9173 const unsigned char *s = (SDATA (it->string)
9174 + IT_STRING_BYTEPOS (*it));
9175 it->c = check_char_and_length (s, &it->len);
9176 }
9177 else
9178 {
9179 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9180 it->len = 1;
9181 }
9182 }
9183
9184
9185 it->what = IT_CHARACTER;
9186 it->object = it->string;
9187 it->position = position;
9188 return true;
9189 }
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199 static bool
9200 next_element_from_c_string (struct it *it)
9201 {
9202 bool success_p = true;
9203
9204 eassert (it->s);
9205 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9206 it->what = IT_CHARACTER;
9207 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9208 it->object = make_fixnum (0);
9209
9210
9211
9212
9213
9214 if (it->bidi_p && it->bidi_it.first_elt)
9215 get_visually_first_element (it);
9216
9217
9218
9219
9220 if (IT_CHARPOS (*it) >= it->end_charpos)
9221 {
9222
9223 it->what = IT_EOB;
9224 success_p = false;
9225 }
9226 else if (IT_CHARPOS (*it) >= it->string_nchars)
9227 {
9228
9229 it->c = ' ', it->len = 1;
9230 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9231 }
9232 else if (it->multibyte_p)
9233 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9234 else
9235 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9236
9237 return success_p;
9238 }
9239
9240
9241
9242
9243
9244
9245
9246 static bool
9247 next_element_from_ellipsis (struct it *it)
9248 {
9249 if (it->selective_display_ellipsis_p)
9250 setup_for_ellipsis (it, it->len);
9251 else
9252 {
9253
9254
9255
9256
9257 it->saved_face_id = it->face_id;
9258 it->method = GET_FROM_BUFFER;
9259 it->object = it->w->contents;
9260 reseat_at_next_visible_line_start (it, true);
9261 it->face_before_selective_p = true;
9262 }
9263
9264 return GET_NEXT_DISPLAY_ELEMENT (it);
9265 }
9266
9267
9268
9269
9270
9271
9272
9273 static bool
9274 next_element_from_image (struct it *it)
9275 {
9276 it->what = IT_IMAGE;
9277 return true;
9278 }
9279
9280 static bool
9281 next_element_from_xwidget (struct it *it)
9282 {
9283 it->what = IT_XWIDGET;
9284 return true;
9285 }
9286
9287
9288
9289
9290
9291
9292 static bool
9293 next_element_from_stretch (struct it *it)
9294 {
9295 it->what = IT_STRETCH;
9296 return true;
9297 }
9298
9299
9300
9301
9302
9303
9304 static void
9305 compute_stop_pos_backwards (struct it *it)
9306 {
9307 const int SCAN_BACK_LIMIT = 1000;
9308 struct text_pos pos;
9309 struct display_pos save_current = it->current;
9310 struct text_pos save_position = it->position;
9311 ptrdiff_t charpos = IT_CHARPOS (*it);
9312 ptrdiff_t where_we_are = charpos;
9313 ptrdiff_t save_stop_pos = it->stop_charpos;
9314 ptrdiff_t save_end_pos = it->end_charpos;
9315
9316 eassert (NILP (it->string) && !it->s);
9317 eassert (it->bidi_p);
9318 it->bidi_p = false;
9319 do
9320 {
9321 it->end_charpos = min (charpos + 1, ZV);
9322 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9323 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9324 reseat_1 (it, pos, false);
9325 compute_stop_pos (it);
9326
9327 if (it->stop_charpos <= charpos)
9328 emacs_abort ();
9329 }
9330 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9331
9332 if (it->stop_charpos <= where_we_are)
9333 it->prev_stop = it->stop_charpos;
9334 else
9335 it->prev_stop = BEGV;
9336 it->bidi_p = true;
9337 it->current = save_current;
9338 it->position = save_position;
9339 it->stop_charpos = save_stop_pos;
9340 it->end_charpos = save_end_pos;
9341 }
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351 static void
9352 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9353 {
9354 bool bufp = !STRINGP (it->string);
9355 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9356 struct display_pos save_current = it->current;
9357 struct text_pos save_position = it->position;
9358 struct composition_it save_cmp_it = it->cmp_it;
9359 struct text_pos pos1;
9360 ptrdiff_t next_stop;
9361
9362
9363 eassert (it->bidi_p);
9364 it->bidi_p = false;
9365 do
9366 {
9367 it->prev_stop = charpos;
9368 if (bufp)
9369 {
9370 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9371 reseat_1 (it, pos1, false);
9372 }
9373 else
9374 it->current.string_pos = string_pos (charpos, it->string);
9375 compute_stop_pos (it);
9376
9377 if (it->stop_charpos <= it->prev_stop)
9378 emacs_abort ();
9379 charpos = it->stop_charpos;
9380 }
9381 while (charpos <= where_we_are);
9382
9383 it->bidi_p = true;
9384 it->current = save_current;
9385 it->position = save_position;
9386 it->cmp_it = save_cmp_it;
9387 next_stop = it->stop_charpos;
9388 it->stop_charpos = it->prev_stop;
9389 handle_stop (it);
9390 it->stop_charpos = next_stop;
9391 }
9392
9393
9394
9395
9396
9397
9398 static bool
9399 next_element_from_buffer (struct it *it)
9400 {
9401 bool success_p = true;
9402
9403 eassert (IT_CHARPOS (*it) >= BEGV);
9404 eassert (NILP (it->string) && !it->s);
9405 eassert (!it->bidi_p
9406 || (NILP (it->bidi_it.string.lstring)
9407 && it->bidi_it.string.s == NULL));
9408
9409
9410
9411
9412
9413 if (it->bidi_p && it->bidi_it.first_elt)
9414 {
9415 get_visually_first_element (it);
9416 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9417 }
9418
9419 if (IT_CHARPOS (*it) >= it->stop_charpos)
9420 {
9421 if (IT_CHARPOS (*it) >= it->end_charpos)
9422 {
9423 bool overlay_strings_follow_p;
9424
9425
9426
9427 if (it->overlay_strings_at_end_processed_p)
9428 overlay_strings_follow_p = false;
9429 else
9430 {
9431 it->overlay_strings_at_end_processed_p = true;
9432 overlay_strings_follow_p = get_overlay_strings (it, 0);
9433 }
9434
9435 if (overlay_strings_follow_p)
9436 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9437 else
9438 {
9439 it->what = IT_EOB;
9440 it->position = it->current.pos;
9441 success_p = false;
9442 }
9443 }
9444 else if (!(!it->bidi_p
9445 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9446 || IT_CHARPOS (*it) == it->stop_charpos))
9447 {
9448
9449
9450
9451
9452
9453
9454 handle_stop_backwards (it, it->stop_charpos);
9455 it->ignore_overlay_strings_at_pos_p = false;
9456 return GET_NEXT_DISPLAY_ELEMENT (it);
9457 }
9458 else
9459 {
9460 if (it->bidi_p)
9461 {
9462
9463
9464 it->prev_stop = it->stop_charpos;
9465
9466
9467
9468 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9469 it->base_level_stop = it->stop_charpos;
9470 }
9471 handle_stop (it);
9472 it->ignore_overlay_strings_at_pos_p = false;
9473 return GET_NEXT_DISPLAY_ELEMENT (it);
9474 }
9475 }
9476 else if (it->bidi_p
9477
9478
9479
9480 && IT_CHARPOS (*it) < it->prev_stop
9481
9482
9483
9484
9485 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9486 {
9487 if (it->base_level_stop <= 0
9488 || IT_CHARPOS (*it) < it->base_level_stop)
9489 {
9490
9491
9492
9493
9494 it->base_level_stop = BEGV;
9495 compute_stop_pos_backwards (it);
9496 handle_stop_backwards (it, it->prev_stop);
9497 }
9498 else
9499 handle_stop_backwards (it, it->base_level_stop);
9500 it->ignore_overlay_strings_at_pos_p = false;
9501 return GET_NEXT_DISPLAY_ELEMENT (it);
9502 }
9503 else
9504 {
9505
9506
9507 unsigned char *p;
9508 ptrdiff_t stop;
9509
9510
9511
9512 it->ignore_overlay_strings_at_pos_p = false;
9513
9514 if (composition_break_at_point
9515 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9516 && !NILP (Vauto_composition_mode))
9517 {
9518
9519 if (it->bidi_it.scan_dir < 0)
9520 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9521 else
9522 stop = (IT_CHARPOS (*it) < PT
9523 && PT < it->end_charpos) ? PT : it->end_charpos;
9524 }
9525 else
9526 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9527 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9528 stop)
9529 && next_element_from_composition (it))
9530 {
9531 return true;
9532 }
9533
9534
9535 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9536 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9537 it->c = string_char_and_length (p, &it->len);
9538 else
9539 it->c = *p, it->len = 1;
9540
9541
9542 it->what = IT_CHARACTER;
9543 it->object = it->w->contents;
9544 it->position = it->current.pos;
9545
9546
9547
9548 if (it->selective)
9549 {
9550 if (it->c == '\n')
9551 {
9552
9553
9554 if (it->selective > 0
9555 && IT_CHARPOS (*it) + 1 < ZV
9556 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9557 IT_BYTEPOS (*it) + 1,
9558 it->selective))
9559 {
9560 success_p = next_element_from_ellipsis (it);
9561 it->dpvec_char_len = -1;
9562 }
9563 }
9564 else if (it->c == '\r' && it->selective == -1)
9565 {
9566
9567
9568
9569 success_p = next_element_from_ellipsis (it);
9570 it->dpvec_char_len = -1;
9571 }
9572 }
9573 }
9574
9575
9576 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9577 return success_p;
9578 }
9579
9580
9581
9582
9583
9584
9585
9586 static bool
9587 next_element_from_composition (struct it *it)
9588 {
9589 it->what = IT_COMPOSITION;
9590 it->len = it->cmp_it.nbytes;
9591 if (STRINGP (it->string))
9592 {
9593 if (it->c < 0)
9594 {
9595 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9596 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9597 return false;
9598 }
9599 it->position = it->current.string_pos;
9600 it->object = it->string;
9601 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9602 IT_STRING_BYTEPOS (*it), it->string);
9603 }
9604 else
9605 {
9606 if (it->c < 0)
9607 {
9608 IT_CHARPOS (*it) += it->cmp_it.nchars;
9609 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9610 if (it->bidi_p)
9611 {
9612 if (it->bidi_it.new_paragraph)
9613 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9614 false);
9615
9616
9617 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9618 bidi_move_to_visually_next (&it->bidi_it);
9619 }
9620 return false;
9621 }
9622 it->position = it->current.pos;
9623 it->object = it->w->contents;
9624 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9625 IT_BYTEPOS (*it), Qnil);
9626 }
9627 return true;
9628 }
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9640 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676 static enum move_it_result
9677 move_it_in_display_line_to (struct it *it,
9678 ptrdiff_t to_charpos, int to_x,
9679 enum move_operation_enum op)
9680 {
9681 enum move_it_result result = MOVE_UNDEFINED;
9682 struct glyph_row *saved_glyph_row;
9683 struct it wrap_it, atpos_it, atx_it, ppos_it;
9684 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9685 void *ppos_data = NULL;
9686 bool may_wrap = false;
9687 enum it_method prev_method = it->method;
9688 ptrdiff_t closest_pos UNINIT;
9689 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9690 bool saw_smaller_pos = prev_pos < to_charpos;
9691 bool line_number_pending = false;
9692
9693
9694 saved_glyph_row = it->glyph_row;
9695 it->glyph_row = NULL;
9696
9697
9698
9699
9700
9701
9702 wrap_it.sp = -1;
9703 atpos_it.sp = -1;
9704 atx_it.sp = -1;
9705
9706
9707
9708
9709
9710
9711
9712
9713 if (it->bidi_p)
9714 {
9715 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9716 {
9717 SAVE_IT (ppos_it, *it, ppos_data);
9718 closest_pos = IT_CHARPOS (*it);
9719 }
9720 else
9721 closest_pos = ZV;
9722 }
9723
9724 #define BUFFER_POS_REACHED_P() \
9725 ((op & MOVE_TO_POS) != 0 \
9726 && BUFFERP (it->object) \
9727 && (IT_CHARPOS (*it) == to_charpos \
9728 || ((!it->bidi_p \
9729 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9730 && IT_CHARPOS (*it) > to_charpos) \
9731 || (it->what == IT_COMPOSITION \
9732 && ((IT_CHARPOS (*it) > to_charpos \
9733 && to_charpos >= it->cmp_it.charpos) \
9734 || (IT_CHARPOS (*it) < to_charpos \
9735 && to_charpos <= it->cmp_it.charpos)))) \
9736 && (it->method == GET_FROM_BUFFER \
9737 || (it->method == GET_FROM_DISPLAY_VECTOR \
9738 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9739
9740 if (it->hpos == 0)
9741 {
9742
9743
9744
9745
9746 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9747 && should_produce_line_number (it))
9748 {
9749 if (it->current_x == it->first_visible_x)
9750 maybe_produce_line_number (it);
9751 else
9752 line_number_pending = true;
9753 }
9754
9755 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9756 handle_line_prefix (it);
9757 }
9758
9759 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9760 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9761
9762 while (true)
9763 {
9764 int x, i, ascent = 0, descent = 0;
9765
9766
9767 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9768 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9769 (IT)->max_descent = descent)
9770
9771
9772
9773 if ((op & MOVE_TO_POS) != 0
9774 && BUFFERP (it->object)
9775 && it->method == GET_FROM_BUFFER
9776 && (((!it->bidi_p
9777
9778
9779
9780
9781 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9782 && IT_CHARPOS (*it) > to_charpos)
9783 || (it->bidi_p
9784 && (prev_method == GET_FROM_IMAGE
9785 || prev_method == GET_FROM_STRETCH
9786 || prev_method == GET_FROM_STRING)
9787
9788 && ((prev_pos < to_charpos
9789 && IT_CHARPOS (*it) >= to_charpos)
9790
9791 || (prev_pos > to_charpos
9792 && IT_CHARPOS (*it) <= to_charpos)))))
9793 {
9794 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9795 {
9796 result = MOVE_POS_MATCH_OR_ZV;
9797 break;
9798 }
9799 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9800
9801
9802
9803 SAVE_IT (atpos_it, *it, atpos_data);
9804 }
9805
9806
9807
9808
9809
9810 if (!get_next_display_element (it))
9811 {
9812 result = MOVE_POS_MATCH_OR_ZV;
9813 break;
9814 }
9815
9816 if (it->line_wrap == TRUNCATE)
9817 {
9818
9819
9820
9821
9822
9823
9824 if (BUFFER_POS_REACHED_P ()
9825 && (it->pixel_width > 0
9826 || IT_CHARPOS (*it) > to_charpos
9827 || it->area != TEXT_AREA))
9828 {
9829 result = MOVE_POS_MATCH_OR_ZV;
9830 break;
9831 }
9832 }
9833 else
9834 {
9835 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9836 {
9837 bool next_may_wrap = may_wrap;
9838
9839 if (char_can_wrap_after (it))
9840 next_may_wrap = true;
9841 else
9842 next_may_wrap = false;
9843
9844 if (may_wrap && char_can_wrap_before (it))
9845 {
9846
9847
9848
9849
9850
9851 if (atpos_it.sp >= 0)
9852 {
9853 RESTORE_IT (it, &atpos_it, atpos_data);
9854 result = MOVE_POS_MATCH_OR_ZV;
9855 goto done;
9856 }
9857 if (atx_it.sp >= 0)
9858 {
9859 RESTORE_IT (it, &atx_it, atx_data);
9860 result = MOVE_X_REACHED;
9861 goto done;
9862 }
9863
9864 SAVE_IT (wrap_it, *it, wrap_data);
9865 }
9866
9867 may_wrap = next_may_wrap;
9868 }
9869 }
9870
9871
9872
9873 ascent = it->max_ascent;
9874 descent = it->max_descent;
9875
9876
9877
9878
9879
9880 x = it->current_x;
9881
9882 PRODUCE_GLYPHS (it);
9883
9884 if (it->area != TEXT_AREA)
9885 {
9886 prev_method = it->method;
9887 if (it->method == GET_FROM_BUFFER)
9888 prev_pos = IT_CHARPOS (*it);
9889 set_iterator_to_next (it, true);
9890 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9891 SET_TEXT_POS (this_line_min_pos,
9892 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9893 if (it->bidi_p
9894 && (op & MOVE_TO_POS)
9895 && IT_CHARPOS (*it) > to_charpos
9896 && IT_CHARPOS (*it) < closest_pos)
9897 closest_pos = IT_CHARPOS (*it);
9898 continue;
9899 }
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916
9917
9918
9919 if (it->nglyphs)
9920 {
9921
9922
9923 int single_glyph_width = it->pixel_width / it->nglyphs;
9924 int new_x;
9925 int x_before_this_char = x;
9926 int hpos_before_this_char = it->hpos;
9927
9928 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9929 {
9930 new_x = x + single_glyph_width;
9931
9932
9933 if ((op & MOVE_TO_X) && new_x > to_x)
9934 {
9935 if (BUFFER_POS_REACHED_P ())
9936 {
9937 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9938 goto buffer_pos_reached;
9939 if (atpos_it.sp < 0)
9940 {
9941 SAVE_IT (atpos_it, *it, atpos_data);
9942 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9943 }
9944 }
9945 else
9946 {
9947 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9948 {
9949 it->current_x = x;
9950 result = MOVE_X_REACHED;
9951 break;
9952 }
9953 if (atx_it.sp < 0)
9954 {
9955 SAVE_IT (atx_it, *it, atx_data);
9956 IT_RESET_X_ASCENT_DESCENT (&atx_it);
9957 }
9958 }
9959 }
9960
9961 if (
9962 it->line_wrap != TRUNCATE
9963 && (
9964 new_x > it->last_visible_x
9965
9966
9967 || (new_x == it->last_visible_x
9968 && FRAME_WINDOW_P (it->f)
9969 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
9970 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
9971 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
9972 {
9973 bool moved_forward = false;
9974
9975 if (
9976
9977 it->hpos == 0
9978 || (new_x == it->last_visible_x
9979 && FRAME_WINDOW_P (it->f)))
9980 {
9981 ++it->hpos;
9982 it->current_x = new_x;
9983
9984
9985
9986 if (i == it->nglyphs - 1)
9987 {
9988
9989
9990
9991 if (BUFFER_POS_REACHED_P ())
9992 {
9993 bool can_wrap = true;
9994
9995
9996
9997
9998
9999 if (it->line_wrap == WORD_WRAP
10000 && wrap_it.sp >= 0
10001 && may_wrap
10002 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10003 {
10004 struct it tem_it;
10005 void *tem_data = NULL;
10006
10007 SAVE_IT (tem_it, *it, tem_data);
10008 set_iterator_to_next (it, true);
10009 if (get_next_display_element (it)
10010 && !char_can_wrap_before (it))
10011 can_wrap = false;
10012 RESTORE_IT (it, &tem_it, tem_data);
10013 }
10014 if (it->line_wrap != WORD_WRAP
10015 || wrap_it.sp < 0
10016
10017
10018
10019
10020
10021
10022
10023 || (may_wrap && can_wrap
10024 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10025 {
10026 it->hpos = hpos_before_this_char;
10027 it->current_x = x_before_this_char;
10028 result = MOVE_POS_MATCH_OR_ZV;
10029 break;
10030 }
10031 if (it->line_wrap == WORD_WRAP
10032 && atpos_it.sp < 0)
10033 {
10034 SAVE_IT (atpos_it, *it, atpos_data);
10035 atpos_it.current_x = x_before_this_char;
10036 atpos_it.hpos = hpos_before_this_char;
10037 }
10038 }
10039
10040 prev_method = it->method;
10041 if (it->method == GET_FROM_BUFFER)
10042 prev_pos = IT_CHARPOS (*it);
10043 set_iterator_to_next (it, true);
10044 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10045 SET_TEXT_POS (this_line_min_pos,
10046 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10047
10048
10049
10050
10051
10052
10053
10054 if (!FRAME_WINDOW_P (it->f)
10055 || ((it->bidi_p
10056 && it->bidi_it.paragraph_dir == R2L)
10057 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10058 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10059 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10060 {
10061 if (!get_next_display_element (it))
10062 {
10063 result = MOVE_POS_MATCH_OR_ZV;
10064 break;
10065 }
10066 moved_forward = true;
10067 if (BUFFER_POS_REACHED_P ())
10068 {
10069 if (ITERATOR_AT_END_OF_LINE_P (it))
10070 result = MOVE_POS_MATCH_OR_ZV;
10071 else
10072 result = MOVE_LINE_CONTINUED;
10073 break;
10074 }
10075 if (ITERATOR_AT_END_OF_LINE_P (it)
10076 && (it->line_wrap != WORD_WRAP
10077 || wrap_it.sp < 0
10078 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10079 {
10080 result = MOVE_NEWLINE_OR_CR;
10081 break;
10082 }
10083 }
10084 }
10085 }
10086 else
10087 IT_RESET_X_ASCENT_DESCENT (it);
10088
10089
10090
10091
10092
10093
10094 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10095
10096
10097
10098
10099
10100 && (!moved_forward || char_can_wrap_before (it)))
10101 {
10102
10103
10104 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10105 && atx_it.sp >= 0)
10106 {
10107 RESTORE_IT (it, &atx_it, atx_data);
10108 atpos_it.sp = -1;
10109 atx_it.sp = -1;
10110 result = MOVE_X_REACHED;
10111 break;
10112 }
10113 }
10114 else if (wrap_it.sp >= 0)
10115 {
10116 RESTORE_IT (it, &wrap_it, wrap_data);
10117 atpos_it.sp = -1;
10118 atx_it.sp = -1;
10119 }
10120
10121 move_trace ("move_it_in: continued at %td\n",
10122 IT_CHARPOS (*it));
10123 result = MOVE_LINE_CONTINUED;
10124 break;
10125 }
10126
10127 if (BUFFER_POS_REACHED_P ())
10128 {
10129 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10130 goto buffer_pos_reached;
10131 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10132 {
10133 SAVE_IT (atpos_it, *it, atpos_data);
10134 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10135 }
10136 }
10137
10138 if (new_x > it->first_visible_x)
10139 {
10140
10141
10142 if (line_number_pending)
10143 {
10144 line_number_pending = false;
10145 it->current_x = it->first_visible_x;
10146 maybe_produce_line_number (it);
10147 it->current_x += new_x - it->first_visible_x;
10148 }
10149
10150
10151 ++it->hpos;
10152 }
10153 }
10154
10155 if (result != MOVE_UNDEFINED)
10156 break;
10157 }
10158 else if (BUFFER_POS_REACHED_P ())
10159 {
10160 buffer_pos_reached:
10161 IT_RESET_X_ASCENT_DESCENT (it);
10162 result = MOVE_POS_MATCH_OR_ZV;
10163 break;
10164 }
10165 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10166 {
10167
10168
10169
10170
10171 eassert (it->nglyphs == 0);
10172 result = MOVE_X_REACHED;
10173 break;
10174 }
10175
10176
10177 if (ITERATOR_AT_END_OF_LINE_P (it))
10178 {
10179
10180
10181
10182
10183 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10184 {
10185 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10186 {
10187 if (closest_pos < ZV)
10188 {
10189 RESTORE_IT (it, &ppos_it, ppos_data);
10190
10191
10192 if (closest_pos != to_charpos)
10193 move_it_in_display_line_to (it, closest_pos, -1,
10194 MOVE_TO_POS);
10195 result = MOVE_POS_MATCH_OR_ZV;
10196 }
10197 else
10198 goto buffer_pos_reached;
10199 }
10200 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10201 && IT_CHARPOS (*it) > to_charpos)
10202 goto buffer_pos_reached;
10203 else
10204 result = MOVE_NEWLINE_OR_CR;
10205 }
10206 else
10207 result = MOVE_NEWLINE_OR_CR;
10208
10209
10210
10211
10212 if (it->line_wrap == TRUNCATE
10213 && it->current_x <= it->first_visible_x
10214 && result == MOVE_NEWLINE_OR_CR
10215 && it->char_to_display == '\n')
10216 {
10217 it->max_ascent = it->ascent;
10218 it->max_descent = it->descent;
10219 }
10220
10221
10222
10223 if (result == MOVE_NEWLINE_OR_CR)
10224 it->constrain_row_ascent_descent_p = false;
10225 break;
10226 }
10227
10228 prev_method = it->method;
10229 if (it->method == GET_FROM_BUFFER)
10230 prev_pos = IT_CHARPOS (*it);
10231
10232
10233
10234
10235
10236
10237
10238
10239
10240 bool overwide_wrap_prefix =
10241 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10242 && it->sp > 0 && it->method == GET_FROM_STRETCH
10243 && it->current_x >= it->last_visible_x
10244 && it->continuation_lines_width > 0
10245 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10246
10247
10248 if (!overwide_wrap_prefix)
10249 set_iterator_to_next (it, true);
10250 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10251 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10252 if (IT_CHARPOS (*it) < to_charpos)
10253 saw_smaller_pos = true;
10254 if (it->bidi_p
10255 && (op & MOVE_TO_POS)
10256 && IT_CHARPOS (*it) >= to_charpos
10257 && IT_CHARPOS (*it) < closest_pos)
10258 closest_pos = IT_CHARPOS (*it);
10259
10260
10261
10262 if (it->line_wrap == TRUNCATE
10263 && it->current_x >= it->last_visible_x)
10264 {
10265 if (!FRAME_WINDOW_P (it->f)
10266 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10267 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10268 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10269 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10270 {
10271 bool at_eob_p = false;
10272
10273 if ((at_eob_p = !get_next_display_element (it))
10274 || BUFFER_POS_REACHED_P ()
10275
10276
10277
10278
10279 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10280 && !saw_smaller_pos
10281 && IT_CHARPOS (*it) > to_charpos))
10282 {
10283 if (it->bidi_p
10284 && !BUFFER_POS_REACHED_P ()
10285 && !at_eob_p && closest_pos < ZV)
10286 {
10287 RESTORE_IT (it, &ppos_it, ppos_data);
10288 if (closest_pos != to_charpos)
10289 move_it_in_display_line_to (it, closest_pos, -1,
10290 MOVE_TO_POS);
10291 }
10292 result = MOVE_POS_MATCH_OR_ZV;
10293 break;
10294 }
10295 if (ITERATOR_AT_END_OF_LINE_P (it))
10296 {
10297 result = MOVE_NEWLINE_OR_CR;
10298 break;
10299 }
10300 }
10301 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10302 && !saw_smaller_pos
10303 && IT_CHARPOS (*it) > to_charpos)
10304 {
10305 if (closest_pos < ZV)
10306 {
10307 RESTORE_IT (it, &ppos_it, ppos_data);
10308 if (closest_pos != to_charpos)
10309 move_it_in_display_line_to (it, closest_pos, -1,
10310 MOVE_TO_POS);
10311 }
10312 result = MOVE_POS_MATCH_OR_ZV;
10313 break;
10314 }
10315 result = MOVE_LINE_TRUNCATED;
10316 break;
10317 }
10318 #undef IT_RESET_X_ASCENT_DESCENT
10319 }
10320
10321 #undef BUFFER_POS_REACHED_P
10322
10323
10324
10325
10326
10327
10328 if (result == MOVE_LINE_CONTINUED
10329 && it->line_wrap == WORD_WRAP
10330 && wrap_it.sp >= 0
10331 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10332 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10333 RESTORE_IT (it, &wrap_it, wrap_data);
10334 else if (atpos_it.sp >= 0)
10335 RESTORE_IT (it, &atpos_it, atpos_data);
10336 else if (atx_it.sp >= 0)
10337 RESTORE_IT (it, &atx_it, atx_data);
10338
10339 done:
10340
10341 if (atpos_data)
10342 bidi_unshelve_cache (atpos_data, true);
10343 if (atx_data)
10344 bidi_unshelve_cache (atx_data, true);
10345 if (wrap_data)
10346 bidi_unshelve_cache (wrap_data, true);
10347 if (ppos_data)
10348 bidi_unshelve_cache (ppos_data, true);
10349
10350
10351
10352 it->glyph_row = saved_glyph_row;
10353 return result;
10354 }
10355
10356
10357 void
10358 move_it_in_display_line (struct it *it,
10359 ptrdiff_t to_charpos, int to_x,
10360 enum move_operation_enum op)
10361 {
10362 if (it->line_wrap == WORD_WRAP
10363 && (op & MOVE_TO_X))
10364 {
10365 struct it save_it;
10366 void *save_data = NULL;
10367 int skip;
10368
10369 SAVE_IT (save_it, *it, save_data);
10370 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10371
10372
10373
10374
10375 if (skip == MOVE_LINE_CONTINUED)
10376 {
10377 int prev_x = max (it->current_x - 1, 0);
10378 RESTORE_IT (it, &save_it, save_data);
10379 move_it_in_display_line_to
10380 (it, -1, prev_x, MOVE_TO_X);
10381 }
10382 else
10383 bidi_unshelve_cache (save_data, true);
10384 }
10385 else
10386 move_it_in_display_line_to (it, to_charpos, to_x, op);
10387 }
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403
10404 int
10405 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10406 {
10407 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10408 int line_height, line_start_x = 0, reached = 0;
10409 int max_current_x = 0;
10410 void *backup_data = NULL;
10411 ptrdiff_t orig_charpos = -1;
10412 enum it_method orig_method = NUM_IT_METHODS;
10413
10414 for (;;)
10415 {
10416 orig_charpos = IT_CHARPOS (*it);
10417 orig_method = it->method;
10418 if (op & MOVE_TO_VPOS)
10419 {
10420
10421
10422 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10423 {
10424 if (it->vpos == to_vpos)
10425 {
10426 reached = 1;
10427 break;
10428 }
10429 else
10430 skip = move_it_in_display_line_to (it, -1, -1, 0);
10431 }
10432 else
10433 {
10434
10435
10436 if (it->vpos == to_vpos)
10437 {
10438 reached = 2;
10439 break;
10440 }
10441
10442 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10443
10444 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10445 {
10446 reached = 3;
10447 break;
10448 }
10449 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10450 {
10451
10452 skip = move_it_in_display_line_to (it, to_charpos,
10453 -1, MOVE_TO_POS);
10454 if (skip == MOVE_POS_MATCH_OR_ZV)
10455 {
10456 reached = 4;
10457 break;
10458 }
10459 }
10460 }
10461 }
10462 else if (op & MOVE_TO_Y)
10463 {
10464 struct it it_backup;
10465
10466 if (it->line_wrap == WORD_WRAP)
10467 SAVE_IT (it_backup, *it, backup_data);
10468
10469
10470
10471
10472
10473
10474
10475
10476
10477
10478
10479
10480
10481 skip = move_it_in_display_line_to
10482 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10483 (MOVE_TO_X | (op & MOVE_TO_POS)));
10484
10485
10486 if (skip == MOVE_POS_MATCH_OR_ZV)
10487 reached = 5;
10488 else if (skip == MOVE_X_REACHED)
10489 {
10490
10491
10492
10493
10494 line_height = it->max_ascent + it->max_descent;
10495 if (to_y >= it->current_y
10496 && to_y < it->current_y + line_height)
10497 {
10498 reached = 6;
10499 break;
10500 }
10501 SAVE_IT (it_backup, *it, backup_data);
10502 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10503 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10504 op & MOVE_TO_POS);
10505 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10506 line_height = it->max_ascent + it->max_descent;
10507 move_trace ("move_it: line_height = %d\n", line_height);
10508
10509 if (to_y >= it->current_y
10510 && to_y < it->current_y + line_height)
10511 {
10512
10513
10514
10515
10516
10517
10518
10519
10520 int max_ascent = it->max_ascent;
10521 int max_descent = it->max_descent;
10522
10523 RESTORE_IT (it, &it_backup, backup_data);
10524 it->max_ascent = max_ascent;
10525 it->max_descent = max_descent;
10526 reached = 6;
10527 }
10528 else
10529 {
10530 skip = skip2;
10531 if (skip == MOVE_POS_MATCH_OR_ZV)
10532 {
10533 reached = 7;
10534
10535
10536
10537
10538
10539
10540
10541 if (to_charpos > 0
10542 && IT_CHARPOS (*it) != to_charpos
10543 && ((IT_CHARPOS (it_backup) > to_charpos)
10544 == (IT_CHARPOS (*it) > to_charpos)))
10545 {
10546 int max_ascent = it->max_ascent;
10547 int max_descent = it->max_descent;
10548
10549 RESTORE_IT (it, &it_backup, backup_data);
10550 it->max_ascent = max_ascent;
10551 it->max_descent = max_descent;
10552 }
10553 }
10554 }
10555 }
10556 else
10557 {
10558
10559 line_height = it->max_ascent + it->max_descent;
10560 move_trace ("move_it: line_height = %d\n", line_height);
10561
10562 if (to_y >= it->current_y
10563 && to_y < it->current_y + line_height)
10564 {
10565 if (to_y > it->current_y)
10566 max_current_x = max (it->current_x, max_current_x);
10567
10568
10569
10570
10571
10572 if (skip == MOVE_LINE_CONTINUED
10573 && it->line_wrap == WORD_WRAP)
10574 {
10575 int prev_x = max (it->current_x - 1, 0);
10576 RESTORE_IT (it, &it_backup, backup_data);
10577 skip = move_it_in_display_line_to
10578 (it, -1, prev_x, MOVE_TO_X);
10579 }
10580
10581 reached = 6;
10582 }
10583 }
10584
10585 if (reached)
10586 {
10587 max_current_x = max (it->current_x, max_current_x);
10588 break;
10589 }
10590 }
10591 else if (BUFFERP (it->object)
10592 && (it->method == GET_FROM_BUFFER
10593 || it->method == GET_FROM_STRETCH)
10594 && IT_CHARPOS (*it) >= to_charpos
10595
10596
10597
10598
10599
10600 && !(it->bidi_p
10601 && it->bidi_it.scan_dir == -1))
10602 skip = MOVE_POS_MATCH_OR_ZV;
10603 else
10604 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10605
10606 switch (skip)
10607 {
10608 case MOVE_POS_MATCH_OR_ZV:
10609 max_current_x = max (it->current_x, max_current_x);
10610 reached = 8;
10611 goto out;
10612
10613 case MOVE_NEWLINE_OR_CR:
10614 max_current_x = max (it->current_x, max_current_x);
10615 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10616 it->override_ascent = -1;
10617 set_iterator_to_next (it, true);
10618 it->continuation_lines_width = 0;
10619 break;
10620
10621 case MOVE_LINE_TRUNCATED:
10622 max_current_x = it->last_visible_x;
10623 it->continuation_lines_width = 0;
10624 reseat_at_next_visible_line_start (it, false);
10625 if ((op & MOVE_TO_POS) != 0
10626 && (IT_CHARPOS (*it) > to_charpos
10627 || (IT_CHARPOS (*it) == to_charpos
10628
10629
10630 && to_charpos == ZV
10631 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10632
10633
10634
10635 && (it->sp == 0
10636 || (STRINGP (it->string)
10637 && (it->current.overlay_string_index < 0
10638 || (it->current.overlay_string_index >= 0
10639 && it->current.overlay_string_index
10640 >= it->n_overlay_strings - 1))
10641 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10642 {
10643 reached = 9;
10644 goto out;
10645 }
10646 break;
10647
10648 case MOVE_LINE_CONTINUED:
10649 max_current_x = it->last_visible_x;
10650
10651
10652
10653
10654 if (it->c == '\t')
10655 {
10656 it->continuation_lines_width += it->last_visible_x;
10657
10658
10659
10660 if (it->current_x != it->last_visible_x
10661 && (op & MOVE_TO_VPOS)
10662 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10663 {
10664 line_start_x = it->current_x + it->pixel_width
10665 - it->last_visible_x;
10666 if (FRAME_WINDOW_P (it->f))
10667 {
10668 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10669 struct font *face_font = face->font;
10670
10671
10672
10673
10674
10675
10676
10677 eassert (face_font);
10678 if (face_font)
10679 {
10680 if (line_start_x < face_font->space_width)
10681 line_start_x
10682 += it->tab_width * face_font->space_width;
10683 }
10684 }
10685 set_iterator_to_next (it, false);
10686 }
10687 }
10688 else
10689 {
10690
10691
10692
10693
10694
10695
10696
10697
10698 if (IT_CHARPOS (*it) == orig_charpos
10699 && it->method == orig_method
10700 && orig_method == GET_FROM_BUFFER)
10701 set_iterator_to_next (it, false);
10702 it->continuation_lines_width += it->current_x;
10703 }
10704 break;
10705
10706 default:
10707 emacs_abort ();
10708 }
10709
10710
10711 it->current_x = line_start_x;
10712 line_start_x = 0;
10713 it->hpos = 0;
10714 it->line_number_produced_p = false;
10715 it->current_y += it->max_ascent + it->max_descent;
10716 ++it->vpos;
10717 last_height = it->max_ascent + it->max_descent;
10718 it->max_ascent = it->max_descent = 0;
10719 }
10720
10721 out:
10722
10723
10724
10725
10726
10727
10728 if (!FRAME_WINDOW_P (it->f)
10729 && op & MOVE_TO_POS
10730 && IT_CHARPOS (*it) == to_charpos
10731 && it->what == IT_CHARACTER
10732 && it->nglyphs > 1
10733 && it->line_wrap == WINDOW_WRAP
10734 && it->current_x == it->last_visible_x - 1
10735 && it->c != '\n'
10736 && it->c != '\t'
10737 && it->w->window_end_valid
10738 && it->vpos < it->w->window_end_vpos)
10739 {
10740 it->continuation_lines_width += it->current_x;
10741 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10742 it->current_y += it->max_ascent + it->max_descent;
10743 ++it->vpos;
10744 last_height = it->max_ascent + it->max_descent;
10745 }
10746
10747 if (backup_data)
10748 bidi_unshelve_cache (backup_data, true);
10749
10750 move_trace ("move_it_to: reached %d\n", reached);
10751
10752 return max_current_x;
10753 }
10754
10755
10756
10757
10758
10759
10760
10761
10762
10763
10764
10765 void
10766 move_it_vertically_backward (struct it *it, int dy)
10767 {
10768 int nlines, h;
10769 struct it it2, it3;
10770 void *it2data = NULL, *it3data = NULL;
10771 ptrdiff_t start_pos;
10772 int nchars_per_row
10773 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10774 ptrdiff_t pos_limit;
10775
10776 move_further_back:
10777 eassert (dy >= 0);
10778
10779 start_pos = IT_CHARPOS (*it);
10780
10781
10782 nlines = max (1, dy / default_line_pixel_height (it->w));
10783 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10784 pos_limit = BEGV;
10785 else
10786 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10787
10788
10789
10790
10791 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10792 back_to_previous_visible_line_start (it);
10793
10794
10795
10796
10797
10798 reseat_1 (it, it->current.pos, true);
10799
10800
10801 it->current_x = it->hpos = 0;
10802
10803 it->continuation_lines_width = 0;
10804
10805
10806
10807
10808
10809 SAVE_IT (it2, *it, it2data);
10810 it2.max_ascent = it2.max_descent = 0;
10811 do
10812 {
10813 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10814 MOVE_TO_POS | MOVE_TO_VPOS);
10815 }
10816 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10817
10818
10819
10820
10821
10822
10823 || (it2.method == GET_FROM_STRING
10824 && IT_CHARPOS (it2) == start_pos
10825 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10826 eassert (IT_CHARPOS (*it) >= BEGV);
10827 SAVE_IT (it3, it2, it3data);
10828
10829 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10830 eassert (IT_CHARPOS (*it) >= BEGV);
10831
10832
10833 h = it2.current_y - it->current_y;
10834
10835 nlines = it2.vpos - it->vpos;
10836
10837
10838
10839 it->vpos -= nlines;
10840 it->current_y -= h;
10841
10842 if (dy == 0)
10843 {
10844
10845
10846
10847 RESTORE_IT (it, it, it2data);
10848 if (nlines > 0)
10849 move_it_by_lines (it, nlines);
10850
10851
10852
10853
10854
10855
10856 if (it->bidi_p
10857 && !it->continuation_lines_width
10858 && !STRINGP (it->string)
10859 && IT_CHARPOS (*it) > BEGV
10860 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10861 {
10862 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10863
10864 dec_both (&cp, &bp);
10865 SET_WITH_NARROWED_BEGV (it, cp,
10866 find_newline_no_quit (cp, bp, -1, NULL),
10867 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10868 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10869 }
10870 bidi_unshelve_cache (it3data, true);
10871 }
10872 else
10873 {
10874
10875
10876 int target_y = it->current_y + h - dy;
10877 int y0 = it3.current_y;
10878 int y1;
10879 int line_height;
10880
10881 RESTORE_IT (&it3, &it3, it3data);
10882 y1 = line_bottom_y (&it3);
10883 line_height = y1 - y0;
10884 RESTORE_IT (it, it, it2data);
10885
10886
10887 if (target_y < it->current_y
10888
10889
10890
10891
10892 && (it->current_y - target_y
10893 > min (window_box_height (it->w), line_height * 2 / 3))
10894 && IT_CHARPOS (*it) > BEGV)
10895 {
10896 move_trace (" not far enough -> move_vert %d\n",
10897 target_y - it->current_y);
10898 dy = it->current_y - target_y;
10899 goto move_further_back;
10900 }
10901 else if (target_y >= it->current_y + line_height
10902 && IT_CHARPOS (*it) < ZV)
10903 {
10904
10905
10906
10907
10908
10909
10910
10911
10912 if (!FRAME_WINDOW_P (it->f))
10913 move_it_vertically (it, target_y - it->current_y);
10914 else
10915 {
10916 struct text_pos last_pos;
10917 int last_y, last_vpos;
10918 do
10919 {
10920 last_pos = it->current.pos;
10921 last_y = it->current_y;
10922 last_vpos = it->vpos;
10923 move_it_by_lines (it, 1);
10924 }
10925 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10926 if (it->current_y > target_y)
10927 {
10928 reseat (it, last_pos, true);
10929 it->current_y = last_y;
10930 it->vpos = last_vpos;
10931 }
10932 }
10933 }
10934 }
10935 }
10936
10937
10938
10939
10940
10941
10942 void
10943 move_it_vertically (struct it *it, int dy)
10944 {
10945 if (dy <= 0)
10946 move_it_vertically_backward (it, -dy);
10947 else
10948 {
10949 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
10950 move_it_to (it, ZV, -1, it->current_y + dy, -1,
10951 MOVE_TO_POS | MOVE_TO_Y);
10952 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
10953
10954
10955
10956 if (IT_CHARPOS (*it) == ZV
10957 && ZV > BEGV
10958 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10959 move_it_by_lines (it, 0);
10960 }
10961 }
10962
10963
10964
10965
10966 void
10967 move_it_past_eol (struct it *it)
10968 {
10969 enum move_it_result rc;
10970
10971 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
10972 if (rc == MOVE_NEWLINE_OR_CR)
10973 set_iterator_to_next (it, false);
10974 }
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985 void
10986 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
10987 {
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005 if (dvpos == 0)
11006 {
11007
11008 move_it_vertically_backward (it, 0);
11009
11010 last_height = 0;
11011 }
11012 else if (dvpos > 0)
11013 {
11014 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
11015 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11016 {
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11028 -1, -1, -1, MOVE_TO_POS);
11029 }
11030 }
11031 else
11032 {
11033 struct it it2;
11034 void *it2data = NULL;
11035 ptrdiff_t start_charpos, orig_charpos, i;
11036 int nchars_per_row
11037 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11038 bool hit_pos_limit = false;
11039 ptrdiff_t pos_limit;
11040
11041
11042
11043
11044 dvpos += it->vpos;
11045 orig_charpos = IT_CHARPOS (*it);
11046 move_it_vertically_backward (it, 0);
11047 dvpos -= it->vpos;
11048
11049
11050
11051 start_charpos = IT_CHARPOS (*it);
11052 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11053 pos_limit = BEGV;
11054 else
11055 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11056
11057 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11058 back_to_previous_visible_line_start (it);
11059 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11060 hit_pos_limit = true;
11061 reseat (it, it->current.pos, true);
11062
11063
11064 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11065 {
11066
11067 dvpos += it->vpos;
11068 move_it_vertically_backward (it, 0);
11069 dvpos -= it->vpos;
11070 if (IT_POS_VALID_AFTER_MOVE_P (it))
11071 break;
11072
11073
11074 back_to_previous_visible_line_start (it);
11075 reseat (it, it->current.pos, true);
11076 dvpos--;
11077 }
11078
11079 it->current_x = it->hpos = 0;
11080
11081
11082
11083 SAVE_IT (it2, *it, it2data);
11084 it2.vpos = it2.current_y = 0;
11085 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11086 it->vpos -= it2.vpos;
11087 it->current_y -= it2.current_y;
11088 it->current_x = it->hpos = 0;
11089
11090
11091 if (it2.vpos > -dvpos)
11092 {
11093 int delta = it2.vpos + dvpos;
11094
11095 RESTORE_IT (&it2, &it2, it2data);
11096 SAVE_IT (it2, *it, it2data);
11097 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11098
11099
11100 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11101 RESTORE_IT (it, &it2, it2data);
11102 else
11103 bidi_unshelve_cache (it2data, true);
11104 }
11105 else if (hit_pos_limit && pos_limit > BEGV
11106 && dvpos < 0 && it2.vpos < -dvpos)
11107 {
11108
11109
11110
11111
11112
11113
11114
11115
11116 dvpos += it2.vpos;
11117 RESTORE_IT (it, it, it2data);
11118 for (i = -dvpos; i > 0; --i)
11119 {
11120 back_to_previous_visible_line_start (it);
11121 it->vpos--;
11122 }
11123 reseat_1 (it, it->current.pos, true);
11124 }
11125 else
11126 RESTORE_IT (it, it, it2data);
11127 }
11128 }
11129
11130 int
11131 partial_line_height (struct it *it_origin)
11132 {
11133
11134
11135
11136
11137
11138 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11139 && it_origin->line_wrap == TRUNCATE)
11140 return 0;
11141
11142 int partial_height;
11143 void *it_data = NULL;
11144 struct it it;
11145 SAVE_IT (it, *it_origin, it_data);
11146 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11147 MOVE_TO_POS | MOVE_TO_Y);
11148 if (it.what == IT_EOB)
11149 {
11150 int vis_height = it.last_visible_y - it.current_y;
11151 int height = it.ascent + it.descent;
11152 partial_height = (vis_height < height) ? vis_height : 0;
11153 }
11154 else
11155 {
11156 int last_line_y = it.current_y;
11157 move_it_by_lines (&it, 1);
11158 partial_height = (it.current_y > it.last_visible_y)
11159 ? it.last_visible_y - last_line_y : 0;
11160 }
11161 RESTORE_IT (&it, &it, it_data);
11162 return partial_height;
11163 }
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176 static enum move_it_result
11177 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11178 {
11179 ptrdiff_t nl_bytepos;
11180 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11181 1, &nl_bytepos);
11182 struct text_pos new_pos;
11183 enum move_it_result move_result;
11184
11185 if (nl_pos - IT_CHARPOS (*it) > nchars)
11186 {
11187 SET_TEXT_POS (new_pos,
11188 IT_CHARPOS (*it) + nchars,
11189 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11190 move_result = MOVE_X_REACHED;
11191 }
11192 else
11193 {
11194 if (nl_bytepos < ZV_BYTE
11195 || (nl_bytepos > BEGV_BYTE
11196 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11197 {
11198 nl_pos--;
11199 nl_bytepos--;
11200 move_result = MOVE_NEWLINE_OR_CR;
11201 }
11202 else
11203 move_result = MOVE_POS_MATCH_OR_ZV;
11204 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11205 }
11206 reseat (it, new_pos, false);
11207 return move_result;
11208 }
11209
11210
11211
11212 bool
11213 in_display_vector_p (struct it *it)
11214 {
11215 return (it->method == GET_FROM_DISPLAY_VECTOR
11216 && it->current.dpvec_index > 0
11217 && it->dpvec + it->current.dpvec_index != it->dpend);
11218 }
11219
11220
11221
11222
11223
11224 static Lisp_Object
11225 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11226 Lisp_Object x_limit, Lisp_Object y_limit,
11227 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11228 {
11229 struct window *w = decode_live_window (window);
11230 struct it it;
11231 ptrdiff_t start, end, bpos;
11232 struct text_pos startp;
11233 void *itdata = NULL;
11234 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11235
11236 if (NILP (from))
11237 {
11238 start = BEGV;
11239 bpos = BEGV_BYTE;
11240 }
11241 else if (EQ (from, Qt))
11242 {
11243 start = BEGV;
11244 bpos = BEGV_BYTE;
11245 while (bpos < ZV_BYTE)
11246 {
11247 c = FETCH_BYTE (bpos);
11248 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11249 break;
11250 inc_both (&start, &bpos);
11251 }
11252 while (bpos > BEGV_BYTE)
11253 {
11254 dec_both (&start, &bpos);
11255 c = FETCH_BYTE (bpos);
11256 if (!(c == ' ' || c == '\t'))
11257 break;
11258 }
11259 }
11260 else if (CONSP (from))
11261 {
11262 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11263 bpos = CHAR_TO_BYTE (start);
11264 CHECK_FIXNUM (XCDR (from));
11265 vertical_offset = XFIXNUM (XCDR (from));
11266 }
11267 else
11268 {
11269 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11270 bpos = CHAR_TO_BYTE (start);
11271 }
11272
11273 SET_TEXT_POS (startp, start, bpos);
11274
11275 if (NILP (to))
11276 end = ZV;
11277 else if (EQ (to, Qt))
11278 {
11279 end = ZV;
11280 bpos = ZV_BYTE;
11281 while (bpos > BEGV_BYTE)
11282 {
11283 dec_both (&end, &bpos);
11284 c = FETCH_BYTE (bpos);
11285 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11286 {
11287 inc_both (&end, &bpos);
11288 break;
11289 }
11290 }
11291 while (bpos < ZV_BYTE)
11292 {
11293 c = fetch_char_advance (&end, &bpos);
11294 if (!(c == ' ' || c == '\t'))
11295 break;
11296 }
11297 }
11298 else
11299 end = clip_to_bounds (start, fix_position (to), ZV);
11300
11301 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11302 max_x = XFIXNUM (x_limit);
11303 else if (!NILP (x_limit))
11304 max_x = INT_MAX;
11305
11306 if (NILP (y_limit))
11307 max_y = INT_MAX;
11308 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11309 max_y = XFIXNUM (y_limit);
11310
11311 itdata = bidi_shelve_cache ();
11312
11313 start_display (&it, w, startp);
11314
11315 int start_y = it.current_y;
11316
11317
11318
11319
11320
11321
11322
11323 it.bidi_p = false;
11324
11325 int start_x;
11326 if (vertical_offset != 0)
11327 {
11328 int last_y;
11329 it.current_y = 0;
11330
11331 move_it_by_lines (&it, 0);
11332
11333
11334
11335
11336
11337 if (vertical_offset < 0)
11338 {
11339 while (it.current_y > vertical_offset)
11340 {
11341 last_y = it.current_y;
11342 move_it_vertically_backward (&it,
11343 (abs (vertical_offset)
11344 + it.current_y));
11345
11346 if (it.current_y == last_y)
11347 break;
11348 }
11349 }
11350 else
11351 {
11352 move_it_vertically (&it, vertical_offset);
11353 }
11354
11355 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11356 + WINDOW_HEADER_LINE_HEIGHT (w));
11357 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11358 start_y = it.current_y;
11359 start_x = it.current_x;
11360 }
11361 else
11362 {
11363
11364
11365
11366 reseat_at_previous_visible_line_start (&it);
11367 it.current_x = it.hpos = 0;
11368 if (IT_CHARPOS (it) != start)
11369 {
11370 void *it1data = NULL;
11371 struct it it1;
11372
11373 SAVE_IT (it1, it, it1data);
11374 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11375
11376
11377
11378
11379
11380 if (IT_CHARPOS (it) > start && start > BEGV)
11381 {
11382 ptrdiff_t it1pos = IT_CHARPOS (it1);
11383 int it1_x = it1.current_x;
11384
11385 RESTORE_IT (&it, &it1, it1data);
11386
11387
11388
11389
11390
11391 if (start - 1 > it1pos)
11392 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11393 else
11394 move_it_in_display_line (&it, start, it1_x + 1,
11395 MOVE_TO_POS | MOVE_TO_X);
11396 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11397 start_x = it.current_x;
11398
11399
11400
11401 if (IT_CHARPOS (it) == start - 1)
11402 start_x += it.pixel_width;
11403 }
11404 else
11405 {
11406 start_x = it.current_x;
11407 bidi_unshelve_cache (it1data, true);
11408 }
11409 }
11410 else
11411 start_x = it.current_x;
11412 }
11413
11414
11415 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11416 int to_x = -1;
11417 it.current_y = start_y;
11418
11419
11420 if (FETCH_BYTE (start) == '\n')
11421 it.current_x = 0;
11422 if (!NILP (x_limit))
11423 {
11424 it.last_visible_x = max_x;
11425
11426
11427
11428 move_op |= MOVE_TO_X;
11429 to_x = INT_MAX;
11430 }
11431
11432 void *it2data = NULL;
11433 struct it it2;
11434 SAVE_IT (it2, it, it2data);
11435
11436 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11437
11438
11439
11440
11441
11442 if (IT_CHARPOS (it) > end)
11443 {
11444 end--;
11445 RESTORE_IT (&it, &it2, it2data);
11446 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11447
11448
11449
11450 if (IT_CHARPOS (it) == end)
11451 {
11452 x += it.pixel_width;
11453
11454
11455 if (!NILP (ignore_line_at_end))
11456 doff = (max (it.max_ascent, it.ascent)
11457 + max (it.max_descent, it.descent));
11458 else
11459 {
11460 it.max_ascent = max (it.max_ascent, it.ascent);
11461 it.max_descent = max (it.max_descent, it.descent);
11462 }
11463 }
11464 }
11465 else
11466 bidi_unshelve_cache (it2data, true);
11467
11468 if (!NILP (x_limit))
11469 {
11470
11471 if (x > max_x)
11472 x = max_x;
11473 }
11474
11475
11476
11477
11478 if (it.current_y > start_y)
11479 start_x = 0;
11480
11481
11482
11483 if (!NILP (ignore_line_at_end))
11484 y = (it.current_y + doff
11485 - WINDOW_TAB_LINE_HEIGHT (w)
11486 - WINDOW_HEADER_LINE_HEIGHT (w));
11487 else
11488 y = (it.current_y + it.max_ascent + it.max_descent + doff
11489 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11490
11491
11492 if (y > max_y)
11493 y = max_y;
11494
11495 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11496 && window_wants_tab_line (w))
11497
11498 {
11499 Lisp_Object window_tab_line_format
11500 = window_parameter (w, Qtab_line_format);
11501
11502 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11503 NILP (window_tab_line_format)
11504 ? BVAR (current_buffer, tab_line_format)
11505 : window_tab_line_format);
11506 }
11507
11508 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11509 && window_wants_header_line (w))
11510 {
11511 Lisp_Object window_header_line_format
11512 = window_parameter (w, Qheader_line_format);
11513
11514 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11515 NILP (window_header_line_format)
11516 ? BVAR (current_buffer, header_line_format)
11517 : window_header_line_format);
11518 }
11519
11520 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11521 && window_wants_mode_line (w))
11522 {
11523 Lisp_Object window_mode_line_format
11524 = window_parameter (w, Qmode_line_format);
11525
11526 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11527 NILP (window_mode_line_format)
11528 ? BVAR (current_buffer, mode_line_format)
11529 : window_mode_line_format);
11530 }
11531
11532 bidi_unshelve_cache (itdata, false);
11533
11534 return (!vertical_offset
11535 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11536 : list3i (x - start_x, y, start));
11537 }
11538
11539 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11540 doc:
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595 )
11596 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11597 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11598 {
11599 struct window *w = decode_live_window (window);
11600 struct buffer *b = XBUFFER (w->contents);
11601 struct buffer *old_b = NULL;
11602 Lisp_Object value;
11603
11604 if (b != current_buffer)
11605 {
11606 old_b = current_buffer;
11607 set_buffer_internal_1 (b);
11608 }
11609
11610 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11611 ignore_line_at_end);
11612
11613 if (old_b)
11614 set_buffer_internal_1 (old_b);
11615
11616 return value;
11617 }
11618
11619 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11620 doc:
11621
11622
11623
11624
11625
11626
11627
11628
11629
11630
11631
11632
11633 )
11634 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11635 Lisp_Object y_limit)
11636 {
11637 struct window *w = decode_live_window (window);
11638 struct buffer *b = (NILP (buffer_or_name)
11639 ? current_buffer
11640 : XBUFFER (Fget_buffer (buffer_or_name)));
11641 Lisp_Object buffer, value;
11642 specpdl_ref count = SPECPDL_INDEX ();
11643
11644 XSETBUFFER (buffer, b);
11645
11646
11647
11648
11649 record_unwind_protect (unwind_with_echo_area_buffer,
11650 with_echo_area_buffer_unwind_data (w));
11651
11652 set_buffer_internal_1 (b);
11653
11654 if (!EQ (buffer, w->contents))
11655 {
11656 wset_buffer (w, buffer);
11657 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11658 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11659 }
11660
11661 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11662 Qnil);
11663
11664 unbind_to (count, Qnil);
11665
11666 return value;
11667 }
11668
11669
11670 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11671 Sdisplay__line_is_continued_p, 0, 0, 0,
11672 doc: )
11673 (void)
11674 {
11675 struct buffer *oldb = current_buffer;
11676 struct window *w = XWINDOW (selected_window);
11677 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11678
11679 set_buffer_internal_1 (XBUFFER (w->contents));
11680
11681 if (PT < ZV)
11682 {
11683 struct text_pos startpos;
11684 struct it it;
11685 void *itdata;
11686
11687
11688 Lisp_Object opoint = Fpoint_marker ();
11689
11690
11691
11692 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11693 SET_TEXT_POS (startpos, PT, PT_BYTE);
11694 itdata = bidi_shelve_cache ();
11695 start_display (&it, w, startpos);
11696
11697 if (it.line_wrap != TRUNCATE)
11698 {
11699 it.glyph_row = NULL;
11700 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11701 }
11702 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11703 bidi_unshelve_cache (itdata, false);
11704 }
11705 set_buffer_internal_1 (oldb);
11706
11707 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11708 }
11709
11710
11711
11712
11713
11714
11715
11716
11717 static ptrdiff_t
11718 format_nargs (char const *format)
11719 {
11720 ptrdiff_t nargs = 0;
11721 for (char const *p = format; (p = strchr (p, '%')); p++)
11722 if (p[1] == '%')
11723 p++;
11724 else
11725 nargs++;
11726 return nargs;
11727 }
11728
11729
11730
11731
11732 void
11733 add_to_log (const char *format, ...)
11734 {
11735 va_list ap;
11736 va_start (ap, format);
11737 vadd_to_log (format, ap);
11738 va_end (ap);
11739 }
11740
11741 void
11742 vadd_to_log (char const *format, va_list ap)
11743 {
11744 ptrdiff_t form_nargs = format_nargs (format);
11745 ptrdiff_t nargs = 1 + form_nargs;
11746 Lisp_Object args[10];
11747 eassert (nargs <= ARRAYELTS (args));
11748 AUTO_STRING (args0, format);
11749 args[0] = args0;
11750 for (ptrdiff_t i = 1; i <= nargs; i++)
11751 args[i] = va_arg (ap, Lisp_Object);
11752 Lisp_Object msg = Qnil;
11753 msg = Fformat_message (nargs, args);
11754
11755 ptrdiff_t len = SBYTES (msg) + 1;
11756 USE_SAFE_ALLOCA;
11757 char *buffer = SAFE_ALLOCA (len);
11758 memcpy (buffer, SDATA (msg), len);
11759
11760 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11761 SAFE_FREE ();
11762 }
11763
11764
11765
11766
11767 void
11768 message_log_maybe_newline (void)
11769 {
11770 if (message_log_need_newline)
11771 message_dolog ("", 0, true, false);
11772 }
11773
11774
11775
11776
11777
11778
11779
11780
11781
11782
11783
11784 void
11785 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11786 {
11787 const unsigned char *msg = (const unsigned char *) m;
11788
11789 if (!NILP (Vmemory_full))
11790 return;
11791
11792 if (!NILP (Vmessage_log_max))
11793 {
11794 struct buffer *oldbuf;
11795 Lisp_Object oldpoint, oldbegv, oldzv;
11796 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11797 ptrdiff_t point_at_end = 0;
11798 ptrdiff_t zv_at_end = 0;
11799 Lisp_Object old_deactivate_mark;
11800
11801 old_deactivate_mark = Vdeactivate_mark;
11802 oldbuf = current_buffer;
11803
11804
11805
11806 if (! STRINGP (Vmessages_buffer_name))
11807 Vmessages_buffer_name = build_string ("*Messages*");
11808
11809
11810 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11811 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11812 if (newbuffer
11813 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11814 call0 (intern ("messages-buffer-mode"));
11815
11816 bset_undo_list (current_buffer, Qt);
11817 bset_cache_long_scans (current_buffer, Qnil);
11818
11819 oldpoint = message_dolog_marker1;
11820 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11821 oldbegv = message_dolog_marker2;
11822 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11823 oldzv = message_dolog_marker3;
11824 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11825
11826 if (PT == Z)
11827 point_at_end = 1;
11828 if (ZV == Z)
11829 zv_at_end = 1;
11830
11831 BEGV = BEG;
11832 BEGV_BYTE = BEG_BYTE;
11833 ZV = Z;
11834 ZV_BYTE = Z_BYTE;
11835 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11836
11837
11838
11839 if (multibyte
11840 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11841 {
11842
11843
11844 for (ptrdiff_t i = 0; i < nbytes; )
11845 {
11846 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11847 char work = CHAR_TO_BYTE8 (c);
11848 insert_1_both (&work, 1, 1, true, false, false);
11849 i += char_bytes;
11850 }
11851 }
11852 else if (! multibyte
11853 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11854 {
11855
11856
11857 for (ptrdiff_t i = 0; i < nbytes; i++)
11858 {
11859 int c = make_char_multibyte (msg[i]);
11860 unsigned char str[MAX_MULTIBYTE_LENGTH];
11861 int char_bytes = CHAR_STRING (c, str);
11862 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11863 }
11864 }
11865 else if (nbytes)
11866 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11867 true, false, false);
11868
11869 if (nlflag)
11870 {
11871 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11872 intmax_t dups;
11873
11874
11875
11876
11877
11878 specpdl_ref count = SPECPDL_INDEX ();
11879 specbind (Qinhibit_modification_hooks, Qt);
11880
11881 insert_1_both ("\n", 1, 1, true, false, false);
11882
11883 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11884 this_bol = PT;
11885 this_bol_byte = PT_BYTE;
11886
11887
11888
11889 if (this_bol > BEG)
11890 {
11891 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11892 prev_bol = PT;
11893 prev_bol_byte = PT_BYTE;
11894
11895 dups = message_log_check_duplicate (prev_bol_byte,
11896 this_bol_byte);
11897 if (dups)
11898 {
11899 del_range_both (prev_bol, prev_bol_byte,
11900 this_bol, this_bol_byte, false);
11901 if (dups > 1)
11902 {
11903 char dupstr[sizeof " [ times]"
11904 + INT_STRLEN_BOUND (dups)];
11905
11906
11907
11908 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11909 dups);
11910 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11911 insert_1_both (dupstr, duplen, duplen,
11912 true, false, true);
11913 }
11914 }
11915 }
11916
11917
11918
11919
11920
11921 if (FIXNATP (Vmessage_log_max))
11922 {
11923 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11924 -XFIXNAT (Vmessage_log_max) - 1, false);
11925 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11926 }
11927
11928 unbind_to (count, Qnil);
11929 }
11930 BEGV = marker_position (oldbegv);
11931 BEGV_BYTE = marker_byte_position (oldbegv);
11932
11933 if (zv_at_end)
11934 {
11935 ZV = Z;
11936 ZV_BYTE = Z_BYTE;
11937 }
11938 else
11939 {
11940 ZV = marker_position (oldzv);
11941 ZV_BYTE = marker_byte_position (oldzv);
11942 }
11943
11944 if (point_at_end)
11945 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11946 else
11947
11948
11949 TEMP_SET_PT_BOTH (marker_position (oldpoint),
11950 marker_byte_position (oldpoint));
11951
11952 unchain_marker (XMARKER (oldpoint));
11953 unchain_marker (XMARKER (oldbegv));
11954 unchain_marker (XMARKER (oldzv));
11955
11956
11957
11958
11959
11960
11961
11962 windows_or_buffers_changed = old_windows_or_buffers_changed;
11963 bset_redisplay (current_buffer);
11964
11965 set_buffer_internal (oldbuf);
11966
11967 message_log_need_newline = !nlflag;
11968 Vdeactivate_mark = old_deactivate_mark;
11969 }
11970 }
11971
11972
11973
11974
11975
11976
11977
11978
11979 static intmax_t
11980 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
11981 {
11982 ptrdiff_t i;
11983 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
11984 bool seen_dots = false;
11985 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
11986 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
11987
11988 for (i = 0; i < len; i++)
11989 {
11990 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
11991 seen_dots = true;
11992 if (p1[i] != p2[i])
11993 return seen_dots;
11994 }
11995 p1 += len;
11996 if (*p1 == '\n')
11997 return 2;
11998 if (*p1++ == ' ' && *p1++ == '[')
11999 {
12000 char *pend;
12001 intmax_t n = strtoimax ((char *) p1, &pend, 10);
12002 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
12003 return n + 1;
12004 }
12005 return 0;
12006 }
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016 void
12017 message3 (Lisp_Object m)
12018 {
12019 clear_message (true, true);
12020 cancel_echoing ();
12021
12022
12023 message_log_maybe_newline ();
12024 if (STRINGP (m))
12025 {
12026 ptrdiff_t nbytes = SBYTES (m);
12027 bool multibyte = STRING_MULTIBYTE (m);
12028 char *buffer;
12029 USE_SAFE_ALLOCA;
12030 SAFE_ALLOCA_STRING (buffer, m);
12031 message_dolog (buffer, nbytes, true, multibyte);
12032 SAFE_FREE ();
12033 }
12034 if (! inhibit_message)
12035 message3_nolog (m);
12036 }
12037
12038
12039
12040 static void
12041 message_to_stderr (Lisp_Object m)
12042 {
12043 if (noninteractive_need_newline)
12044 {
12045 noninteractive_need_newline = false;
12046 errputc ('\n');
12047 }
12048 if (STRINGP (m))
12049 {
12050 Lisp_Object coding_system = Vlocale_coding_system;
12051 Lisp_Object s;
12052
12053 if (!NILP (Vcoding_system_for_write))
12054 coding_system = Vcoding_system_for_write;
12055 if (!NILP (coding_system))
12056 s = code_convert_string_norecord (m, coding_system, true);
12057 else
12058 s = m;
12059
12060 errwrite (SDATA (s), SBYTES (s));
12061 }
12062 if (STRINGP (m) || !cursor_in_echo_area)
12063 errputc ('\n');
12064 }
12065
12066
12067
12068
12069
12070
12071 void
12072 message3_nolog (Lisp_Object m)
12073 {
12074 struct frame *sf = SELECTED_FRAME ();
12075
12076 if (FRAME_INITIAL_P (sf))
12077 message_to_stderr (m);
12078
12079
12080
12081 else if (INTERACTIVE && sf->glyphs_initialized_p)
12082 {
12083
12084
12085 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12086 Lisp_Object frame = XWINDOW (mini_window)->frame;
12087 struct frame *f = XFRAME (frame);
12088
12089 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12090 Fmake_frame_visible (frame);
12091
12092 if (STRINGP (m) && SCHARS (m) > 0)
12093 {
12094 set_message (m);
12095 if (minibuffer_auto_raise)
12096 Fraise_frame (frame);
12097
12098
12099 echo_message_buffer = Qnil;
12100 }
12101 else
12102 clear_message (true, true);
12103
12104 do_pending_window_change (false);
12105 echo_area_display (true);
12106 do_pending_window_change (false);
12107 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12108 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12109 }
12110 }
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121 void
12122 message1 (const char *m)
12123 {
12124 message3 (m ? build_unibyte_string (m) : Qnil);
12125 }
12126
12127
12128
12129
12130 void
12131 message1_nolog (const char *m)
12132 {
12133 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12134 }
12135
12136
12137
12138
12139 void
12140 message_with_string (const char *m, Lisp_Object string, bool log)
12141 {
12142 CHECK_STRING (string);
12143
12144 bool need_message;
12145 if (noninteractive)
12146 need_message = !!m;
12147 else if (!INTERACTIVE)
12148 need_message = false;
12149 else
12150 {
12151
12152
12153
12154 Lisp_Object mini_window;
12155 struct frame *f, *sf = SELECTED_FRAME ();
12156
12157
12158
12159 mini_window = FRAME_MINIBUF_WINDOW (sf);
12160 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12161
12162
12163
12164
12165 need_message = f->glyphs_initialized_p;
12166 }
12167
12168 if (need_message)
12169 {
12170 AUTO_STRING (fmt, m);
12171 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12172
12173 if (noninteractive)
12174 message_to_stderr (msg);
12175 else
12176 {
12177 if (log)
12178 message3 (msg);
12179 else
12180 message3_nolog (msg);
12181
12182
12183
12184 message_buf_print = false;
12185 }
12186 }
12187 }
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12201 vmessage (const char *m, va_list ap)
12202 {
12203 if (noninteractive)
12204 {
12205 if (m)
12206 {
12207 if (noninteractive_need_newline)
12208 putc ('\n', stderr);
12209 noninteractive_need_newline = false;
12210 vfprintf (stderr, m, ap);
12211 if (!cursor_in_echo_area)
12212 putc ('\n', stderr);
12213 fflush (stderr);
12214 }
12215 }
12216 else if (INTERACTIVE)
12217 {
12218
12219
12220
12221 Lisp_Object mini_window;
12222 struct frame *f, *sf = SELECTED_FRAME ();
12223
12224
12225
12226 mini_window = FRAME_MINIBUF_WINDOW (sf);
12227 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12228
12229
12230
12231
12232 if (f->glyphs_initialized_p)
12233 {
12234 if (m)
12235 {
12236 ptrdiff_t len;
12237 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12238 USE_SAFE_ALLOCA;
12239 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12240
12241 len = doprnt (message_buf, maxsize, m, 0, ap);
12242
12243 message3 (make_string (message_buf, len));
12244 SAFE_FREE ();
12245 }
12246 else
12247 message1 (0);
12248
12249
12250
12251 message_buf_print = false;
12252 }
12253 }
12254 }
12255
12256
12257 void
12258 message (const char *m, ...)
12259 {
12260 va_list ap;
12261 va_start (ap, m);
12262 vmessage (m, ap);
12263 va_end (ap);
12264 }
12265
12266
12267
12268
12269
12270
12271 void
12272 update_echo_area (void)
12273 {
12274 if (!NILP (echo_area_buffer[0]))
12275 {
12276 Lisp_Object string;
12277 string = Fcurrent_message ();
12278 message3 (string);
12279 }
12280 }
12281
12282
12283
12284
12285
12286 static void
12287 ensure_echo_area_buffers (void)
12288 {
12289 for (int i = 0; i < 2; i++)
12290 if (!BUFFERP (echo_buffer[i])
12291 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12292 {
12293 Lisp_Object old_buffer = echo_buffer[i];
12294 static char const name_fmt[] = " *Echo Area %d*";
12295 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12296 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12297 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12298 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12299
12300
12301
12302
12303 for (int j = 0; j < 2; j++)
12304 if (EQ (old_buffer, echo_area_buffer[j]))
12305 echo_area_buffer[j] = echo_buffer[i];
12306 }
12307 }
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326 static bool
12327 with_echo_area_buffer (struct window *w, int which,
12328 bool (*fn) (void *, Lisp_Object),
12329 void *a1, Lisp_Object a2)
12330 {
12331 Lisp_Object buffer;
12332 bool this_one, the_other, clear_buffer_p, rc;
12333 specpdl_ref count = SPECPDL_INDEX ();
12334
12335
12336 ensure_echo_area_buffers ();
12337
12338 clear_buffer_p = false;
12339
12340 if (which == 0)
12341 this_one = false, the_other = true;
12342 else if (which > 0)
12343 this_one = true, the_other = false;
12344 else
12345 {
12346 this_one = false, the_other = true;
12347 clear_buffer_p = true;
12348
12349
12350
12351 if (!NILP (echo_area_buffer[this_one])
12352 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12353 echo_area_buffer[this_one] = Qnil;
12354 }
12355
12356
12357
12358 if (NILP (echo_area_buffer[this_one]))
12359 {
12360 echo_area_buffer[this_one]
12361 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12362 ? echo_buffer[the_other]
12363 : echo_buffer[this_one]);
12364 clear_buffer_p = true;
12365 }
12366
12367 buffer = echo_area_buffer[this_one];
12368
12369
12370
12371 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12372 cancel_echoing ();
12373
12374 record_unwind_protect (unwind_with_echo_area_buffer,
12375 with_echo_area_buffer_unwind_data (w));
12376
12377
12378
12379
12380
12381
12382
12383
12384 set_buffer_internal_1 (XBUFFER (buffer));
12385 if (w)
12386 {
12387 wset_buffer (w, buffer);
12388 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12389 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12390 }
12391
12392 bset_undo_list (current_buffer, Qt);
12393 bset_read_only (current_buffer, Qnil);
12394 specbind (Qinhibit_read_only, Qt);
12395 specbind (Qinhibit_modification_hooks, Qt);
12396
12397 if (clear_buffer_p && Z > BEG)
12398 del_range (BEG, Z);
12399
12400 eassert (BEGV >= BEG);
12401 eassert (ZV <= Z && ZV >= BEGV);
12402
12403 rc = fn (a1, a2);
12404
12405 eassert (BEGV >= BEG);
12406 eassert (ZV <= Z && ZV >= BEGV);
12407
12408 unbind_to (count, Qnil);
12409 return rc;
12410 }
12411
12412
12413
12414
12415
12416 static Lisp_Object
12417 with_echo_area_buffer_unwind_data (struct window *w)
12418 {
12419 int i = 0;
12420 Lisp_Object vector, tmp;
12421
12422
12423
12424 vector = Vwith_echo_area_save_vector;
12425 Vwith_echo_area_save_vector = Qnil;
12426
12427 if (NILP (vector))
12428 vector = make_nil_vector (11);
12429
12430 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12431 ASET (vector, i, Vdeactivate_mark); ++i;
12432 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12433
12434 if (w)
12435 {
12436 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12437 ASET (vector, i, w->contents); ++i;
12438 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12439 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12440 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12441 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12442 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12443 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12444 }
12445 else
12446 {
12447 int end = i + 8;
12448 for (; i < end; ++i)
12449 ASET (vector, i, Qnil);
12450 }
12451
12452 eassert (i == ASIZE (vector));
12453 return vector;
12454 }
12455
12456
12457
12458
12459
12460 static void
12461 unwind_with_echo_area_buffer (Lisp_Object vector)
12462 {
12463 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12464 Vdeactivate_mark = AREF (vector, 1);
12465 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12466
12467 if (WINDOWP (AREF (vector, 3)))
12468 {
12469 struct window *w;
12470 Lisp_Object buffer;
12471
12472 w = XWINDOW (AREF (vector, 3));
12473 buffer = AREF (vector, 4);
12474
12475 wset_buffer (w, buffer);
12476 set_marker_restricted_both (w->pointm, buffer,
12477 XFIXNAT (AREF (vector, 5)),
12478 XFIXNAT (AREF (vector, 6)));
12479 set_marker_restricted_both (w->old_pointm, buffer,
12480 XFIXNAT (AREF (vector, 7)),
12481 XFIXNAT (AREF (vector, 8)));
12482 set_marker_restricted_both (w->start, buffer,
12483 XFIXNAT (AREF (vector, 9)),
12484 XFIXNAT (AREF (vector, 10)));
12485 }
12486
12487 Vwith_echo_area_save_vector = vector;
12488 }
12489
12490
12491
12492
12493
12494 void
12495 setup_echo_area_for_printing (bool multibyte_p)
12496 {
12497
12498 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12499 Fkill_emacs (Qnil, Qnil);
12500
12501 ensure_echo_area_buffers ();
12502
12503 if (!message_buf_print)
12504 {
12505
12506
12507 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12508 echo_area_buffer[0] = echo_buffer[1];
12509 else
12510 echo_area_buffer[0] = echo_buffer[0];
12511
12512
12513 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12514 bset_truncate_lines (current_buffer, Qnil);
12515
12516 if (Z > BEG)
12517 {
12518 specpdl_ref count = SPECPDL_INDEX ();
12519 specbind (Qinhibit_read_only, Qt);
12520
12521 del_range (BEG, Z);
12522 unbind_to (count, Qnil);
12523 }
12524 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12525
12526
12527
12528
12529
12530
12531
12532 if (unibyte_display_via_language_environment
12533 && !multibyte_p
12534 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12535 Fset_buffer_multibyte (Qnil);
12536 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12537 Fset_buffer_multibyte (Qt);
12538
12539
12540 if (minibuffer_auto_raise)
12541 {
12542 struct frame *sf = SELECTED_FRAME ();
12543 Lisp_Object mini_window;
12544 mini_window = FRAME_MINIBUF_WINDOW (sf);
12545 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12546 }
12547
12548 message_log_maybe_newline ();
12549 message_buf_print = true;
12550 }
12551 else
12552 {
12553 if (NILP (echo_area_buffer[0]))
12554 {
12555 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12556 echo_area_buffer[0] = echo_buffer[1];
12557 else
12558 echo_area_buffer[0] = echo_buffer[0];
12559 }
12560
12561 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12562 {
12563
12564 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12565 bset_truncate_lines (current_buffer, Qnil);
12566 }
12567 }
12568 }
12569
12570
12571
12572
12573
12574
12575
12576 static bool
12577 display_echo_area (struct window *w)
12578 {
12579 bool no_message_p, window_height_changed_p;
12580
12581
12582
12583
12584
12585
12586 specpdl_ref count = inhibit_garbage_collection ();
12587
12588
12589
12590
12591
12592 bool i = display_last_displayed_message_p;
12593
12594
12595
12596 no_message_p = NILP (echo_area_buffer[i]);
12597
12598 window_height_changed_p
12599 = with_echo_area_buffer (w, display_last_displayed_message_p,
12600 display_echo_area_1, w, Qnil);
12601
12602 if (no_message_p)
12603 echo_area_buffer[i] = Qnil;
12604
12605 unbind_to (count, Qnil);
12606 return window_height_changed_p;
12607 }
12608
12609
12610
12611
12612
12613
12614
12615
12616 static bool
12617 display_echo_area_1 (void *a1, Lisp_Object a2)
12618 {
12619 struct window *w = a1;
12620 Lisp_Object window;
12621 struct text_pos start;
12622
12623
12624
12625
12626 forget_escape_and_glyphless_faces ();
12627
12628
12629
12630
12631 bool window_height_changed_p = resize_mini_window (w, false);
12632
12633
12634 SET_TEXT_POS_FROM_MARKER (start, w->start);
12635
12636
12637 clear_glyph_matrix (w->desired_matrix);
12638 XSETWINDOW (window, w);
12639 void *itdata = bidi_shelve_cache ();
12640 try_window (window, start, 0);
12641 bidi_unshelve_cache (itdata, false);
12642
12643 return window_height_changed_p;
12644 }
12645
12646
12647
12648
12649
12650
12651 void
12652 resize_echo_area_exactly (void)
12653 {
12654 if (BUFFERP (echo_area_buffer[0])
12655 && WINDOWP (echo_area_window))
12656 {
12657 struct window *w = XWINDOW (echo_area_window);
12658 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12659 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12660 w, resize_exactly);
12661 if (resized_p)
12662 {
12663 windows_or_buffers_changed = 42;
12664 update_mode_lines = 30;
12665 redisplay_internal ();
12666 }
12667 }
12668 }
12669
12670
12671
12672
12673
12674
12675
12676
12677 static bool
12678 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12679 {
12680 return resize_mini_window (a1, !NILP (exactly));
12681 }
12682
12683
12684
12685
12686
12687
12688
12689
12690
12691
12692
12693
12694
12695 bool
12696 resize_mini_window (struct window *w, bool exact_p)
12697 {
12698 struct frame *f = XFRAME (w->frame);
12699 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12700
12701 eassert (MINI_WINDOW_P (w));
12702
12703
12704
12705
12706
12707
12708
12709 if (!NILP (Vinhibit_redisplay))
12710 return false;
12711
12712
12713 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12714 set_marker_both (w->start, w->contents,
12715 BUF_BEGV (XBUFFER (w->contents)),
12716 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12717
12718
12719 if ((NILP (Vresize_mini_windows)
12720 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12721 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12722 return false;
12723
12724 if (FRAME_MINIBUF_ONLY_P (f))
12725 {
12726 if (!NILP (resize_mini_frames))
12727 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12728 }
12729 else
12730 {
12731 struct it it;
12732 int unit = FRAME_LINE_HEIGHT (f);
12733 int height, max_height;
12734 struct text_pos start;
12735 struct buffer *old_current_buffer = NULL;
12736 int windows_height = FRAME_INNER_HEIGHT (f);
12737
12738 if (current_buffer != XBUFFER (w->contents))
12739 {
12740 old_current_buffer = current_buffer;
12741 set_buffer_internal (XBUFFER (w->contents));
12742 }
12743
12744 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12745
12746
12747 if (FLOATP (Vmax_mini_window_height))
12748 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12749 else if (FIXNUMP (Vmax_mini_window_height))
12750 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12751 else
12752 max_height = windows_height / 4;
12753
12754
12755 max_height = clip_to_bounds (unit, max_height, windows_height);
12756
12757
12758 last_height = 0;
12759 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12760
12761
12762 if (it.max_ascent == 0 && it.max_descent == 0)
12763 {
12764 height = it.current_y;
12765
12766
12767
12768
12769
12770 if (!(it.line_wrap == TRUNCATE
12771 && it.current_x <= it.first_visible_x
12772 && ZV_BYTE > 1
12773 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12774 height += last_height;
12775 }
12776 else
12777 height = it.current_y + it.max_ascent + it.max_descent;
12778 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12779
12780
12781 if (height > max_height)
12782 {
12783 height = (max_height / unit) * unit;
12784 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12785 {
12786 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12787 move_it_vertically_backward (&it, height - unit);
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797 move_it_by_lines (&it, 0);
12798 start = it.current.pos;
12799
12800
12801 w->start_at_line_beg = false;
12802 SET_MARKER_FROM_TEXT_POS (w->start, start);
12803 }
12804 }
12805 else
12806 {
12807 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12808 SET_MARKER_FROM_TEXT_POS (w->start, start);
12809 }
12810
12811 if (EQ (Vresize_mini_windows, Qgrow_only))
12812 {
12813
12814
12815 if (height > old_height)
12816 grow_mini_window (w, height - old_height);
12817 else if (height < old_height && (exact_p || BEGV == ZV))
12818 shrink_mini_window (w);
12819 }
12820 else if (height != old_height)
12821
12822 grow_mini_window (w, height - old_height);
12823
12824 if (old_current_buffer)
12825 set_buffer_internal (old_current_buffer);
12826 }
12827
12828 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12829 }
12830
12831
12832
12833
12834
12835 Lisp_Object
12836 current_message (void)
12837 {
12838 Lisp_Object msg;
12839
12840 if (!BUFFERP (echo_area_buffer[0]))
12841 msg = Qnil;
12842 else
12843 {
12844 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12845 if (NILP (msg))
12846 echo_area_buffer[0] = Qnil;
12847 }
12848
12849 return msg;
12850 }
12851
12852
12853 static bool
12854 current_message_1 (void *a1, Lisp_Object a2)
12855 {
12856 Lisp_Object *msg = a1;
12857
12858 if (Z > BEG)
12859 *msg = make_buffer_string (BEG, Z, true);
12860 else
12861 *msg = Qnil;
12862 return false;
12863 }
12864
12865
12866
12867
12868
12869
12870
12871 bool
12872 push_message (void)
12873 {
12874 Lisp_Object msg = current_message ();
12875 Vmessage_stack = Fcons (msg, Vmessage_stack);
12876 return STRINGP (msg);
12877 }
12878
12879
12880
12881
12882 void
12883 restore_message (void)
12884 {
12885 eassert (CONSP (Vmessage_stack));
12886 message3_nolog (XCAR (Vmessage_stack));
12887 }
12888
12889
12890
12891
12892 void
12893 pop_message_unwind (void)
12894 {
12895
12896 eassert (CONSP (Vmessage_stack));
12897 Vmessage_stack = XCDR (Vmessage_stack);
12898 }
12899
12900
12901
12902
12903
12904
12905 void
12906 check_message_stack (void)
12907 {
12908 if (!NILP (Vmessage_stack))
12909 emacs_abort ();
12910 }
12911
12912 void
12913 clear_message_stack (void)
12914 {
12915 Vmessage_stack = Qnil;
12916 }
12917
12918
12919
12920
12921 void
12922 truncate_echo_area (ptrdiff_t nchars)
12923 {
12924 if (nchars == 0)
12925 echo_area_buffer[0] = Qnil;
12926 else if (!noninteractive
12927 && INTERACTIVE
12928 && !NILP (echo_area_buffer[0]))
12929 {
12930 struct frame *sf = SELECTED_FRAME ();
12931
12932
12933
12934 if (sf->glyphs_initialized_p)
12935 with_echo_area_buffer (0, 0, truncate_message_1,
12936 (void *) (intptr_t) nchars, Qnil);
12937 }
12938 }
12939
12940
12941
12942
12943
12944 static bool
12945 truncate_message_1 (void *a1, Lisp_Object a2)
12946 {
12947 intptr_t nchars = (intptr_t) a1;
12948 if (BEG + nchars < Z)
12949 del_range (BEG + nchars, Z);
12950 if (Z == BEG)
12951 echo_area_buffer[0] = Qnil;
12952 return false;
12953 }
12954
12955 extern intptr_t garbage_collection_inhibited;
12956
12957
12958
12959 static void
12960 set_message (Lisp_Object string)
12961 {
12962 Lisp_Object message = Qnil;
12963
12964 eassert (STRINGP (string));
12965
12966 if (FUNCTIONP (Vset_message_function)
12967
12968
12969
12970 && !garbage_collection_inhibited)
12971 {
12972 specpdl_ref count = SPECPDL_INDEX ();
12973 specbind (Qinhibit_quit, Qt);
12974 message = safe_call1 (Vset_message_function, string);
12975 unbind_to (count, Qnil);
12976
12977 if (STRINGP (message))
12978 {
12979 string = message;
12980 message = Qnil;
12981 }
12982 }
12983
12984 if (NILP (message))
12985 {
12986 message_enable_multibyte = STRING_MULTIBYTE (string);
12987
12988 with_echo_area_buffer (0, -1, set_message_1, 0, string);
12989 message_buf_print = false;
12990 help_echo_showing_p = false;
12991 }
12992
12993 if (STRINGP (Vdebug_on_message)
12994 && STRINGP (string)
12995 && fast_string_match (Vdebug_on_message, string) >= 0)
12996 call_debugger (list2 (Qerror, string));
12997 }
12998
12999
13000
13001
13002
13003
13004 static bool
13005 set_message_1 (void *a1, Lisp_Object string)
13006 {
13007 eassert (STRINGP (string));
13008
13009
13010
13011
13012
13013
13014 if (!message_enable_multibyte
13015 && unibyte_display_via_language_environment
13016 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13017 Fset_buffer_multibyte (Qnil);
13018 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13019 Fset_buffer_multibyte (Qt);
13020
13021 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13022 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13023 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13024
13025
13026 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13027
13028
13029
13030
13031 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13032
13033 return false;
13034 }
13035
13036
13037
13038
13039
13040 void
13041 clear_message (bool current_p, bool last_displayed_p)
13042 {
13043 Lisp_Object preserve = Qnil;
13044
13045 if (current_p)
13046 {
13047 if (FUNCTIONP (Vclear_message_function)
13048
13049 && !garbage_collection_inhibited)
13050 {
13051 specpdl_ref count = SPECPDL_INDEX ();
13052 specbind (Qinhibit_quit, Qt);
13053 preserve = safe_call (1, Vclear_message_function);
13054 unbind_to (count, Qnil);
13055 }
13056
13057 if (!EQ (preserve, Qdont_clear_message))
13058 {
13059 echo_area_buffer[0] = Qnil;
13060 message_cleared_p = true;
13061 }
13062 }
13063
13064 if (last_displayed_p)
13065 echo_area_buffer[1] = Qnil;
13066
13067 message_buf_print = false;
13068 }
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
13079 static void
13080 clear_garbaged_frames (void)
13081 {
13082 if (frame_garbaged)
13083 {
13084 Lisp_Object tail, frame;
13085 struct frame *sf = SELECTED_FRAME ();
13086
13087 FOR_EACH_FRAME (tail, frame)
13088 {
13089 struct frame *f = XFRAME (frame);
13090
13091 if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
13092 {
13093 if (f->resized_p
13094
13095
13096
13097
13098
13099 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13100 redraw_frame (f);
13101 else
13102 clear_current_matrices (f);
13103
13104 #ifdef HAVE_WINDOW_SYSTEM
13105 if (FRAME_WINDOW_P (f)
13106 && FRAME_RIF (f)->clear_under_internal_border)
13107 FRAME_RIF (f)->clear_under_internal_border (f);
13108 #endif
13109 fset_redisplay (f);
13110 f->garbaged = false;
13111 f->resized_p = false;
13112 }
13113 }
13114
13115 frame_garbaged = false;
13116 }
13117 }
13118
13119
13120
13121
13122
13123 static void
13124 echo_area_display (bool update_frame_p)
13125 {
13126 Lisp_Object mini_window;
13127 struct window *w;
13128 struct frame *f;
13129 bool window_height_changed_p = false;
13130 struct frame *sf = SELECTED_FRAME ();
13131
13132 mini_window = FRAME_MINIBUF_WINDOW (sf);
13133 if (NILP (mini_window))
13134 return;
13135
13136 w = XWINDOW (mini_window);
13137 f = XFRAME (WINDOW_FRAME (w));
13138
13139
13140 if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
13141 return;
13142
13143 #ifdef HAVE_WINDOW_SYSTEM
13144
13145
13146
13147 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13148 return;
13149 #endif
13150
13151
13152 clear_garbaged_frames ();
13153
13154 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13155 {
13156 echo_area_window = mini_window;
13157 window_height_changed_p = display_echo_area (w);
13158 w->must_be_updated_p = true;
13159
13160
13161
13162
13163
13164 if (update_frame_p && !redisplaying_p)
13165 {
13166 int n = 0;
13167
13168
13169
13170
13171
13172
13173 if (!display_completed)
13174 {
13175 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13176
13177 #ifdef HAVE_WINDOW_SYSTEM
13178 if (FRAME_WINDOW_P (f)
13179 && FRAME_RIF (f)->clear_under_internal_border)
13180 FRAME_RIF (f)->clear_under_internal_border (f);
13181 #endif
13182 }
13183
13184 if (window_height_changed_p
13185
13186
13187 && !NILP (Vrun_hooks))
13188 {
13189
13190
13191
13192 specpdl_ref count = SPECPDL_INDEX ();
13193 specbind (Qredisplay_dont_pause, Qt);
13194 fset_redisplay (f);
13195 redisplay_internal ();
13196 unbind_to (count, Qnil);
13197 }
13198 else if (FRAME_WINDOW_P (f) && n == 0)
13199 {
13200
13201
13202
13203 update_single_window (w);
13204 flush_frame (f);
13205 }
13206 else
13207 update_frame (f, true, true);
13208
13209
13210
13211
13212 if (cursor_in_echo_area)
13213 wset_redisplay (XWINDOW (mini_window));
13214 }
13215 }
13216 else if (!EQ (mini_window, selected_window))
13217 wset_redisplay (XWINDOW (mini_window));
13218
13219
13220 echo_area_buffer[1] = echo_area_buffer[0];
13221
13222 echo_message_buffer = Qnil;
13223
13224
13225
13226
13227 if (EQ (mini_window, selected_window))
13228 CHARPOS (this_line_start_pos) = 0;
13229
13230 if (window_height_changed_p)
13231 {
13232 fset_redisplay (f);
13233
13234
13235
13236
13237
13238 clear_garbaged_frames ();
13239 }
13240 }
13241
13242
13243
13244 static bool
13245 window_buffer_changed (struct window *w)
13246 {
13247 struct buffer *b = XBUFFER (w->contents);
13248
13249 eassert (BUFFER_LIVE_P (b));
13250
13251 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13252 }
13253
13254
13255
13256 static bool
13257 mode_line_update_needed (struct window *w)
13258 {
13259 return (w->column_number_displayed != -1
13260 && !(PT == w->last_point && !window_outdated (w))
13261 && (w->column_number_displayed != current_column ()));
13262 }
13263
13264
13265
13266
13267 static bool
13268 window_frozen_p (struct window *w)
13269 {
13270 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13271 {
13272 Lisp_Object window;
13273
13274 XSETWINDOW (window, w);
13275 if (MINI_WINDOW_P (w))
13276 return false;
13277 else if (EQ (window, selected_window))
13278 return false;
13279 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13280 && EQ (window, Vminibuf_scroll_window))
13281
13282 return false;
13283 else
13284 return true;
13285 }
13286 return false;
13287 }
13288
13289
13290
13291
13292
13293
13294
13295
13296
13297 static char *mode_line_noprop_buf;
13298
13299
13300
13301 static char *mode_line_noprop_buf_end;
13302 static char *mode_line_noprop_ptr;
13303
13304 #define MODE_LINE_NOPROP_LEN(start) \
13305 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13306
13307 static enum {
13308 MODE_LINE_DISPLAY = 0,
13309 MODE_LINE_TITLE,
13310 MODE_LINE_NOPROP,
13311 MODE_LINE_STRING
13312 } mode_line_target;
13313
13314
13315
13316 static Lisp_Object mode_line_proptrans_alist;
13317
13318
13319 static Lisp_Object mode_line_string_list;
13320
13321
13322 static Lisp_Object mode_line_string_face;
13323 static Lisp_Object mode_line_string_face_prop;
13324
13325
13326
13327
13328 static Lisp_Object Vmode_line_unwind_vector;
13329
13330 static Lisp_Object
13331 format_mode_line_unwind_data (struct frame *target_frame,
13332 struct buffer *obuf,
13333 Lisp_Object owin,
13334 bool save_proptrans)
13335 {
13336 Lisp_Object vector, tmp;
13337
13338
13339
13340 vector = Vmode_line_unwind_vector;
13341 Vmode_line_unwind_vector = Qnil;
13342
13343 if (NILP (vector))
13344 vector = make_nil_vector (12);
13345
13346 ASET (vector, 0, make_fixnum (mode_line_target));
13347 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13348 ASET (vector, 2, mode_line_string_list);
13349 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13350 ASET (vector, 4, mode_line_string_face);
13351 ASET (vector, 5, mode_line_string_face_prop);
13352
13353 if (obuf)
13354 XSETBUFFER (tmp, obuf);
13355 else
13356 tmp = Qnil;
13357 ASET (vector, 6, tmp);
13358 ASET (vector, 7, owin);
13359 if (target_frame)
13360 {
13361 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13362 struct buffer *b = XBUFFER (buffer);
13363 struct buffer *cb = current_buffer;
13364
13365
13366
13367
13368 ASET (vector, 8, target_frame->selected_window);
13369 if (FRAME_TERMCAP_P (target_frame))
13370 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13371
13372
13373
13374
13375 ASET (vector, 10, buffer);
13376 current_buffer = b;
13377 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13378 current_buffer = cb;
13379 }
13380
13381 return vector;
13382 }
13383
13384 static void
13385 unwind_format_mode_line (Lisp_Object vector)
13386 {
13387 Lisp_Object old_window = AREF (vector, 7);
13388 Lisp_Object target_frame_window = AREF (vector, 8);
13389 Lisp_Object old_top_frame = AREF (vector, 9);
13390
13391 mode_line_target = XFIXNUM (AREF (vector, 0));
13392 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13393 mode_line_string_list = AREF (vector, 2);
13394 if (! EQ (AREF (vector, 3), Qt))
13395 mode_line_proptrans_alist = AREF (vector, 3);
13396 mode_line_string_face = AREF (vector, 4);
13397 mode_line_string_face_prop = AREF (vector, 5);
13398
13399
13400 if (WINDOW_LIVE_P (old_window))
13401 {
13402
13403
13404
13405 if (WINDOW_LIVE_P (target_frame_window))
13406 {
13407 Lisp_Object frame
13408 = WINDOW_FRAME (XWINDOW (target_frame_window));
13409
13410 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13411 Fselect_window (target_frame_window, Qt);
13412
13413 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13414
13415
13416 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13417 Fselect_frame (old_top_frame, Qt);
13418 }
13419
13420 Fselect_window (old_window, Qt);
13421
13422
13423
13424
13425 if (WINDOW_LIVE_P (target_frame_window))
13426 {
13427 Lisp_Object buffer = AREF (vector, 10);
13428
13429 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13430 {
13431 struct buffer *cb = current_buffer;
13432
13433 current_buffer = XBUFFER (buffer);
13434 set_point_from_marker (AREF (vector, 11));
13435 ASET (vector, 11, Qnil);
13436 current_buffer = cb;
13437 }
13438 }
13439 }
13440
13441 if (!NILP (AREF (vector, 6)))
13442 {
13443 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13444 ASET (vector, 6, Qnil);
13445 }
13446
13447 Vmode_line_unwind_vector = vector;
13448 }
13449
13450
13451
13452
13453
13454 static void
13455 store_mode_line_noprop_char (char c)
13456 {
13457
13458
13459 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13460 {
13461 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13462 ptrdiff_t size = len;
13463 mode_line_noprop_buf =
13464 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13465 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13466 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13467 }
13468
13469 *mode_line_noprop_ptr++ = c;
13470 }
13471
13472
13473
13474
13475
13476
13477
13478
13479
13480
13481 static int
13482 store_mode_line_noprop (const char *string, int field_width, int precision)
13483 {
13484 const unsigned char *str = (const unsigned char *) string;
13485 int n = 0;
13486 ptrdiff_t dummy, nbytes;
13487
13488
13489 nbytes = strlen (string);
13490 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13491 while (nbytes--)
13492 store_mode_line_noprop_char (*str++);
13493
13494
13495 while (field_width > 0
13496 && n < field_width)
13497 {
13498 store_mode_line_noprop_char (' ');
13499 ++n;
13500 }
13501
13502 return n;
13503 }
13504
13505
13506
13507
13508
13509 #ifdef HAVE_WINDOW_SYSTEM
13510
13511
13512
13513
13514
13515 void
13516 gui_consider_frame_title (Lisp_Object frame)
13517 {
13518 struct frame *f = XFRAME (frame);
13519 Lisp_Object format_data;
13520
13521 if ((FRAME_WINDOW_P (f)
13522 || FRAME_MINIBUF_ONLY_P (f)
13523 || f->explicit_name)
13524 && !FRAME_TOOLTIP_P (f))
13525 {
13526
13527 Lisp_Object tail, other_frame, fmt;
13528 ptrdiff_t title_start;
13529 char *title;
13530 ptrdiff_t len;
13531 struct it it;
13532 specpdl_ref count = SPECPDL_INDEX ();
13533
13534 FOR_EACH_FRAME (tail, other_frame)
13535 {
13536 struct frame *tf = XFRAME (other_frame);
13537
13538 if (tf != f
13539 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13540 && !FRAME_MINIBUF_ONLY_P (tf)
13541 && !FRAME_PARENT_FRAME (tf)
13542 && !FRAME_TOOLTIP_P (tf)
13543 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13544 break;
13545 }
13546
13547
13548 multiple_frames = CONSP (tail);
13549
13550
13551
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561 specbind (Qinhibit_redisplay, Qt);
13562
13563
13564
13565
13566
13567
13568
13569
13570 format_data = format_mode_line_unwind_data (f, current_buffer,
13571 selected_window,
13572 false);
13573 record_unwind_protect (unwind_format_mode_line, format_data);
13574
13575 Fselect_window (f->selected_window, Qt);
13576 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13577 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13578 ? Vicon_title_format : Vframe_title_format);
13579
13580 mode_line_target = MODE_LINE_TITLE;
13581 title_start = MODE_LINE_NOPROP_LEN (0);
13582 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13583 NULL, DEFAULT_FACE_ID);
13584 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13585 len = MODE_LINE_NOPROP_LEN (title_start);
13586 title = mode_line_noprop_buf + title_start;
13587
13588
13589 ptrdiff_t nchars = 0;
13590 len = str_as_multibyte ((unsigned char *) title,
13591 mode_line_noprop_buf_end - title,
13592 len, &nchars);
13593 unbind_to (count, Qnil);
13594
13595
13596
13597
13598
13599
13600 if ((! STRINGP (f->name)
13601 || SBYTES (f->name) != len
13602 || memcmp (title, SDATA (f->name), len) != 0)
13603 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13604 {
13605 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13606 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13607 }
13608 }
13609 }
13610
13611 #endif
13612
13613
13614
13615
13616
13617
13618
13619 #define REDISPLAY_SOME_P() \
13620 ((windows_or_buffers_changed == 0 \
13621 || windows_or_buffers_changed == REDISPLAY_SOME) \
13622 && (update_mode_lines == 0 \
13623 || update_mode_lines == REDISPLAY_SOME))
13624
13625 static bool
13626 needs_no_redisplay (struct window *w)
13627 {
13628 struct buffer *buffer = XBUFFER (w->contents);
13629 struct frame *f = XFRAME (w->frame);
13630 return (REDISPLAY_SOME_P ()
13631 && !w->redisplay
13632 && !w->update_mode_line
13633 && !f->face_change
13634 && !f->redisplay
13635 && !buffer->text->redisplay
13636 && window_point (w) == w->last_point);
13637 }
13638
13639
13640
13641
13642 static void
13643 prepare_menu_bars (void)
13644 {
13645 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13646 bool some_windows = REDISPLAY_SOME_P ();
13647
13648 if (FUNCTIONP (Vpre_redisplay_function))
13649 {
13650 Lisp_Object windows = all_windows ? Qt : Qnil;
13651 if (all_windows && some_windows)
13652 {
13653 Lisp_Object ws = window_list ();
13654 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13655 {
13656 Lisp_Object this = XCAR (ws);
13657 struct window *w = XWINDOW (this);
13658
13659
13660 if (!needs_no_redisplay (w))
13661 windows = Fcons (this, windows);
13662 }
13663 }
13664 safe__call1 (true, Vpre_redisplay_function, windows);
13665 }
13666
13667
13668
13669
13670 #ifdef HAVE_WINDOW_SYSTEM
13671 if (all_windows)
13672 {
13673 Lisp_Object tail, frame;
13674
13675 FOR_EACH_FRAME (tail, frame)
13676 {
13677 struct frame *f = XFRAME (frame);
13678 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13679 if (some_windows
13680 && !f->redisplay
13681 && !w->redisplay
13682 && !XBUFFER (w->contents)->text->redisplay)
13683 continue;
13684
13685 if (!FRAME_TOOLTIP_P (f)
13686 && (FRAME_ICONIFIED_P (f)
13687 || FRAME_VISIBLE_P (f) == 1
13688
13689
13690
13691
13692
13693
13694
13695
13696
13697 || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
13698 gui_consider_frame_title (frame);
13699 }
13700 }
13701 #endif
13702
13703
13704
13705
13706 if (all_windows)
13707 {
13708 Lisp_Object tail, frame;
13709 specpdl_ref count = SPECPDL_INDEX ();
13710
13711
13712 bool menu_bar_hooks_run = false;
13713
13714 record_unwind_save_match_data ();
13715
13716 FOR_EACH_FRAME (tail, frame)
13717 {
13718 struct frame *f = XFRAME (frame);
13719 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13720
13721
13722 if (FRAME_TOOLTIP_P (f))
13723 continue;
13724
13725 if (some_windows
13726 && !f->redisplay
13727 && !w->redisplay
13728 && !XBUFFER (w->contents)->text->redisplay)
13729 continue;
13730
13731 if (!FRAME_PARENT_FRAME (f))
13732 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13733
13734 update_tab_bar (f, false);
13735 #ifdef HAVE_WINDOW_SYSTEM
13736 update_tool_bar (f, false);
13737 #endif
13738 }
13739
13740 unbind_to (count, Qnil);
13741 }
13742 else
13743 {
13744 struct frame *sf = SELECTED_FRAME ();
13745
13746 if (!FRAME_PARENT_FRAME (sf))
13747 update_menu_bar (sf, true, false);
13748
13749 update_tab_bar (sf, true);
13750 #ifdef HAVE_WINDOW_SYSTEM
13751 update_tool_bar (sf, true);
13752 #endif
13753 }
13754 }
13755
13756
13757
13758
13759
13760
13761
13762
13763
13764
13765
13766
13767
13768 static bool
13769 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13770 {
13771 Lisp_Object window;
13772 struct window *w;
13773
13774
13775
13776
13777 if (inhibit_menubar_update)
13778 return hooks_run;
13779
13780 window = FRAME_SELECTED_WINDOW (f);
13781 w = XWINDOW (window);
13782
13783 if (FRAME_WINDOW_P (f)
13784 ?
13785 #ifdef HAVE_EXT_MENU_BAR
13786 FRAME_EXTERNAL_MENU_BAR (f)
13787 #else
13788 FRAME_MENU_BAR_LINES (f) > 0
13789 #endif
13790 : FRAME_MENU_BAR_LINES (f) > 0)
13791 {
13792
13793
13794
13795
13796
13797
13798
13799 if (windows_or_buffers_changed
13800
13801
13802 || update_mode_lines
13803 || window_buffer_changed (w))
13804 {
13805 struct buffer *prev = current_buffer;
13806 specpdl_ref count = SPECPDL_INDEX ();
13807
13808 specbind (Qinhibit_menubar_update, Qt);
13809
13810 set_buffer_internal_1 (XBUFFER (w->contents));
13811 if (save_match_data)
13812 record_unwind_save_match_data ();
13813 if (NILP (Voverriding_local_map_menu_flag))
13814 {
13815 specbind (Qoverriding_terminal_local_map, Qnil);
13816 specbind (Qoverriding_local_map, Qnil);
13817 }
13818
13819 if (!hooks_run)
13820 {
13821
13822 safe_run_hooks (Qactivate_menubar_hook);
13823
13824
13825
13826 safe_run_hooks (Qmenu_bar_update_hook);
13827
13828 hooks_run = true;
13829 }
13830
13831 XSETFRAME (Vmenu_updating_frame, f);
13832 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13833
13834
13835 #ifdef HAVE_EXT_MENU_BAR
13836 if (FRAME_WINDOW_P (f))
13837 {
13838 #if defined (HAVE_NS)
13839
13840
13841 if (f == SELECTED_FRAME ())
13842 #endif
13843 set_frame_menubar (f, false);
13844 }
13845 else
13846
13847
13848 w->update_mode_line = true;
13849 #else
13850
13851
13852 w->update_mode_line = true;
13853 #endif
13854
13855 unbind_to (count, Qnil);
13856 set_buffer_internal_1 (prev);
13857 }
13858 }
13859
13860 return hooks_run;
13861 }
13862
13863
13864
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874 static void
13875 restore_selected_window (Lisp_Object window)
13876 {
13877 if (WINDOW_LIVE_P (window))
13878
13879
13880 {
13881 selected_window = window;
13882 selected_frame = XWINDOW (window)->frame;
13883 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13884 }
13885 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13886
13887
13888 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13889 else
13890
13891
13892
13893 {
13894 Lisp_Object tail;
13895 Lisp_Object frame UNINIT;
13896
13897 FOR_EACH_FRAME (tail, frame)
13898 {
13899 struct frame *f = XFRAME (frame);
13900
13901 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13902 {
13903 selected_frame = frame;
13904 selected_window = FRAME_SELECTED_WINDOW (f);
13905
13906 return;
13907 }
13908 }
13909
13910
13911 emacs_abort ();
13912 }
13913 }
13914
13915
13916 static void
13917 restore_frame_selected_window (Lisp_Object window)
13918 {
13919 if (WINDOW_LIVE_P (window))
13920
13921
13922
13923 {
13924 Lisp_Object frame = XWINDOW (window)->frame;
13925
13926 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13927 if (EQ (frame, selected_frame))
13928 selected_window = window;
13929 }
13930 }
13931
13932
13933
13934
13935
13936
13937 static void
13938 update_tab_bar (struct frame *f, bool save_match_data)
13939 {
13940 bool do_update = false;
13941
13942 #ifdef HAVE_WINDOW_SYSTEM
13943 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
13944 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
13945 do_update = true;
13946 }
13947 else
13948 #endif
13949 if (FRAME_TAB_BAR_LINES (f) > 0)
13950 do_update = true;
13951
13952 if (do_update)
13953 {
13954 Lisp_Object window;
13955 struct window *w;
13956
13957 window = FRAME_SELECTED_WINDOW (f);
13958 w = XWINDOW (window);
13959
13960
13961
13962
13963
13964
13965
13966
13967 if (windows_or_buffers_changed
13968 || w->update_mode_line
13969 || update_mode_lines
13970 || window_buffer_changed (w))
13971 {
13972 struct buffer *prev = current_buffer;
13973 specpdl_ref count = SPECPDL_INDEX ();
13974 Lisp_Object new_tab_bar;
13975 int new_n_tab_bar;
13976
13977
13978
13979
13980 set_buffer_internal_1 (XBUFFER (w->contents));
13981
13982
13983 if (save_match_data)
13984 record_unwind_save_match_data ();
13985
13986
13987 if (NILP (Voverriding_local_map_menu_flag))
13988 {
13989 specbind (Qoverriding_terminal_local_map, Qnil);
13990 specbind (Qoverriding_local_map, Qnil);
13991 }
13992
13993
13994
13995
13996
13997 eassert (EQ (selected_window,
13998
13999
14000 XFRAME (selected_frame)->selected_window));
14001 #ifdef HAVE_WINDOW_SYSTEM
14002 Lisp_Object frame;
14003 record_unwind_protect (restore_selected_window, selected_window);
14004 XSETFRAME (frame, f);
14005 selected_frame = frame;
14006 selected_window = FRAME_SELECTED_WINDOW (f);
14007 #endif
14008
14009
14010 new_tab_bar
14011 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
14012 &new_n_tab_bar);
14013
14014
14015 if (new_n_tab_bar != f->n_tab_bar_items
14016 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14017 {
14018
14019
14020
14021 block_input ();
14022 fset_tab_bar_items (f, new_tab_bar);
14023 f->n_tab_bar_items = new_n_tab_bar;
14024 w->update_mode_line = true;
14025 unblock_input ();
14026 }
14027
14028 unbind_to (count, Qnil);
14029 set_buffer_internal_1 (prev);
14030 }
14031 }
14032 }
14033
14034
14035
14036
14037
14038
14039
14040
14041
14042
14043
14044 static void
14045 display_tab_bar (struct window *w)
14046 {
14047 struct frame *f = XFRAME (WINDOW_FRAME (w));
14048 struct it it;
14049 Lisp_Object items;
14050 int i;
14051
14052
14053 #ifdef HAVE_NTGUI
14054 if (FRAME_W32_P (f))
14055 return;
14056 #endif
14057 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14058 if (FRAME_X_P (f))
14059 return;
14060 #endif
14061
14062 #ifdef HAVE_NS
14063 if (FRAME_NS_P (f))
14064 return;
14065 #endif
14066
14067 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14068 eassert (!FRAME_WINDOW_P (f));
14069 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14070 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14071 TAB_BAR_FACE_ID);
14072 it.first_visible_x = 0;
14073 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14074 #elif defined (HAVE_X_WINDOWS)
14075 if (FRAME_WINDOW_P (f))
14076 {
14077
14078
14079 struct window *tab_w;
14080 tab_w = XWINDOW (f->tab_bar_window);
14081 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14082 TAB_BAR_FACE_ID);
14083 it.first_visible_x = 0;
14084 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14085 }
14086 else
14087 #endif
14088 {
14089
14090
14091 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14092 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14093 TAB_BAR_FACE_ID);
14094 it.first_visible_x = 0;
14095 it.last_visible_x = FRAME_COLS (f);
14096 }
14097
14098
14099
14100
14101 it.paragraph_embedding = L2R;
14102
14103
14104 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14105 {
14106 struct glyph_row *row = it.glyph_row + i;
14107 clear_glyph_row (row);
14108 row->enabled_p = true;
14109 row->full_width_p = true;
14110 row->reversed_p = false;
14111 }
14112
14113
14114 items = it.f->tab_bar_items;
14115 int j;
14116 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14117 {
14118 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14119
14120
14121 if (NILP (string))
14122 break;
14123
14124 if (it.current_x < it.last_visible_x)
14125 display_string (NULL, string, Qnil, 0, 0, &it,
14126 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14127 }
14128
14129
14130 if (it.current_x < it.last_visible_x)
14131 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14132
14133
14134 compute_line_metrics (&it);
14135 }
14136
14137 #ifdef HAVE_WINDOW_SYSTEM
14138
14139
14140
14141
14142
14143 static void
14144 build_desired_tab_bar_string (struct frame *f)
14145 {
14146 int i;
14147 Lisp_Object caption;
14148
14149 caption = Qnil;
14150
14151
14152 fset_desired_tab_bar_string (f, build_string (""));
14153
14154
14155
14156
14157 for (i = 0; i < f->n_tab_bar_items; ++i)
14158 {
14159 #define PROP(IDX) \
14160 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14161
14162 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14163
14164
14165
14166
14167
14168 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14169
14170 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14171 props, caption);
14172
14173 f->desired_tab_bar_string =
14174 concat2 (f->desired_tab_bar_string, caption);
14175
14176 #undef PROP
14177 }
14178 }
14179
14180
14181
14182
14183
14184
14185
14186
14187
14188
14189
14190
14191
14192
14193 static void
14194 display_tab_bar_line (struct it *it, int height)
14195 {
14196 struct glyph_row *row = it->glyph_row;
14197 int max_x = it->last_visible_x;
14198 struct glyph *last;
14199
14200
14201 clear_glyph_row (row);
14202 row->enabled_p = true;
14203 row->y = it->current_y;
14204
14205
14206
14207 it->start_of_box_run_p = true;
14208
14209 bool enough = false;
14210 while (it->current_x < max_x)
14211 {
14212 int x, n_glyphs_before, i, nglyphs;
14213 struct it it_before;
14214
14215
14216 if (!get_next_display_element (it))
14217 {
14218
14219 if (height < 0 && !it->hpos)
14220 return;
14221 break;
14222 }
14223
14224
14225 n_glyphs_before = row->used[TEXT_AREA];
14226 it_before = *it;
14227
14228 PRODUCE_GLYPHS (it);
14229
14230 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14231 i = 0;
14232 x = it_before.current_x;
14233 while (i < nglyphs)
14234 {
14235 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14236
14237 if (x + glyph->pixel_width > max_x)
14238 {
14239
14240 row->used[TEXT_AREA] = n_glyphs_before;
14241 *it = it_before;
14242
14243
14244
14245 if (n_glyphs_before == 0
14246 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14247 break;
14248 goto out;
14249 }
14250
14251 ++it->hpos;
14252 x += glyph->pixel_width;
14253 ++i;
14254 }
14255
14256 enough = ITERATOR_AT_END_OF_LINE_P (it);
14257 set_iterator_to_next (it, true);
14258
14259
14260 if (enough)
14261 break;
14262 }
14263
14264 out:;
14265
14266 row->displays_text_p = row->used[TEXT_AREA] != 0;
14267
14268
14269
14270
14271
14272
14273
14274 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14275 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14276 it->face_id = DEFAULT_FACE_ID;
14277
14278 extend_face_to_end_of_line (it);
14279 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14280 last->right_box_line_p = true;
14281 if (last == row->glyphs[TEXT_AREA])
14282 last->left_box_line_p = true;
14283
14284
14285 if ((height -= it->max_ascent + it->max_descent) > 0)
14286 {
14287
14288 height %= FRAME_LINE_HEIGHT (it->f);
14289 it->max_ascent += height / 2;
14290 it->max_descent += (height + 1) / 2;
14291 }
14292
14293 compute_line_metrics (it);
14294
14295
14296 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14297 {
14298 row->height = row->phys_height = it->last_visible_y - row->y;
14299 row->visible_height = row->height;
14300 row->ascent = row->phys_ascent = 0;
14301 row->extra_line_spacing = 0;
14302 }
14303
14304 row->full_width_p = true;
14305 row->continued_p = false;
14306 row->truncated_on_left_p = false;
14307 row->truncated_on_right_p = false;
14308
14309 it->current_x = it->hpos = 0;
14310 it->current_y += row->height;
14311 ++it->vpos;
14312 ++it->glyph_row;
14313 }
14314
14315
14316
14317
14318
14319 static int
14320 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14321 {
14322 struct window *w = XWINDOW (f->tab_bar_window);
14323 struct it it;
14324
14325
14326
14327 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14328
14329
14330
14331 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14332 temp_row->reversed_p = false;
14333 it.first_visible_x = 0;
14334 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14335 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14336 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14337 it.paragraph_embedding = L2R;
14338
14339 clear_glyph_row (temp_row);
14340 while (!ITERATOR_AT_END_P (&it))
14341 {
14342 it.glyph_row = temp_row;
14343 display_tab_bar_line (&it, -1);
14344 }
14345 clear_glyph_row (temp_row);
14346
14347
14348 if (n_rows)
14349 *n_rows = it.vpos > 0 ? it.vpos : -1;
14350
14351 if (pixelwise)
14352 return it.current_y;
14353 else
14354 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14355 }
14356
14357 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14358 0, 2, 0,
14359 doc:
14360
14361 )
14362 (Lisp_Object frame, Lisp_Object pixelwise)
14363 {
14364 int height = 0;
14365
14366 struct frame *f = decode_any_frame (frame);
14367
14368 if (WINDOWP (f->tab_bar_window)
14369 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14370 {
14371 update_tab_bar (f, true);
14372 if (f->n_tab_bar_items)
14373 {
14374 build_desired_tab_bar_string (f);
14375 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14376 }
14377 }
14378
14379 return make_fixnum (height);
14380 }
14381
14382
14383
14384
14385 static bool
14386 redisplay_tab_bar (struct frame *f)
14387 {
14388 struct window *w;
14389 struct it it;
14390 struct glyph_row *row;
14391
14392 f->tab_bar_redisplayed = true;
14393
14394
14395
14396
14397
14398 if (!WINDOWP (f->tab_bar_window)
14399 || (w = XWINDOW (f->tab_bar_window),
14400 WINDOW_TOTAL_LINES (w) == 0))
14401 {
14402
14403
14404
14405
14406
14407 f->tab_bar_resized = true;
14408
14409 return false;
14410 }
14411
14412
14413 build_desired_tab_bar_string (f);
14414
14415 int new_nrows;
14416 int new_height = tab_bar_height (f, &new_nrows, true);
14417
14418 if (f->n_tab_bar_rows == 0)
14419 {
14420 f->n_tab_bar_rows = new_nrows;
14421 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14422 frame_default_tab_bar_height = new_height;
14423 }
14424
14425
14426
14427 if (new_nrows > f->n_tab_bar_rows
14428 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14429 && !f->minimize_tab_bar_window_p
14430 && new_height > WINDOW_PIXEL_HEIGHT (w))
14431 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14432 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14433 {
14434 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14435 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14436 if (new_nrows != f->n_tab_bar_rows)
14437 f->n_tab_bar_rows = new_nrows;
14438 clear_glyph_matrix (w->desired_matrix);
14439 f->fonts_changed = true;
14440 return true;
14441 }
14442
14443
14444 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14445 it.first_visible_x = 0;
14446 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14447 row = it.glyph_row;
14448 row->reversed_p = false;
14449 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14450 STRING_MULTIBYTE (f->desired_tab_bar_string));
14451
14452
14453
14454
14455
14456
14457
14458 it.paragraph_embedding = L2R;
14459
14460
14461
14462 if (f->n_tab_bar_rows > 0)
14463 {
14464 int border, rows, height, extra;
14465
14466 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14467 border = XFIXNUM (Vtab_bar_border);
14468 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14469 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14470 else if (EQ (Vtab_bar_border, Qborder_width))
14471 border = f->border_width;
14472 else
14473 border = 0;
14474 if (border < 0)
14475 border = 0;
14476
14477 rows = f->n_tab_bar_rows;
14478 height = max (1, (it.last_visible_y - border) / rows);
14479 extra = it.last_visible_y - border - height * rows;
14480
14481 while (it.current_y < it.last_visible_y)
14482 {
14483 int h = 0;
14484 if (extra > 0 && rows-- > 0)
14485 {
14486 h = (extra + rows - 1) / rows;
14487 extra -= h;
14488 }
14489 display_tab_bar_line (&it, height + h);
14490 }
14491 }
14492 else
14493 {
14494 while (it.current_y < it.last_visible_y)
14495 display_tab_bar_line (&it, 0);
14496 }
14497
14498
14499
14500 w->desired_matrix->no_scrolling_p = true;
14501 w->must_be_updated_p = true;
14502
14503 if (!NILP (Vauto_resize_tab_bars))
14504 {
14505 bool change_height_p = false;
14506
14507
14508
14509 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14510 change_height_p = true;
14511
14512
14513
14514
14515
14516 row = it.glyph_row - 1;
14517
14518
14519
14520
14521 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14522 && row->height >= FRAME_LINE_HEIGHT (f))
14523 change_height_p = true;
14524
14525
14526
14527 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14528 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14529 change_height_p = true;
14530
14531
14532
14533 if (change_height_p)
14534 {
14535 int nrows;
14536 int new_height = tab_bar_height (f, &nrows, true);
14537
14538 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14539 && !f->minimize_tab_bar_window_p)
14540 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14541 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14542 f->minimize_tab_bar_window_p = false;
14543
14544 if (change_height_p)
14545 {
14546 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14547 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14548 frame_default_tab_bar_height = new_height;
14549 clear_glyph_matrix (w->desired_matrix);
14550 f->n_tab_bar_rows = nrows;
14551 f->fonts_changed = true;
14552
14553 return true;
14554 }
14555 }
14556 }
14557
14558 f->minimize_tab_bar_window_p = false;
14559 return false;
14560 }
14561
14562
14563
14564
14565
14566
14567
14568 static bool
14569 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14570 int *prop_idx, bool *close_p)
14571 {
14572 Lisp_Object prop;
14573 ptrdiff_t charpos;
14574
14575
14576
14577
14578 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14579 charpos = max (0, charpos);
14580
14581
14582
14583
14584 prop = Fget_text_property (make_fixnum (charpos),
14585 Qmenu_item, f->current_tab_bar_string);
14586 if (! FIXNUMP (prop))
14587 return false;
14588
14589 *prop_idx = XFIXNUM (prop);
14590
14591 if (close_p)
14592 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14593 Qclose_tab,
14594 f->current_tab_bar_string));
14595
14596 return true;
14597 }
14598
14599
14600
14601
14602
14603
14604
14605
14606
14607
14608
14609
14610
14611
14612
14613
14614
14615
14616
14617
14618
14619 static int
14620 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14621 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14622 {
14623 struct window *w = XWINDOW (f->tab_bar_window);
14624 int area;
14625
14626
14627 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14628 if (*glyph == NULL)
14629 return -1;
14630
14631
14632
14633 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14634 return -1;
14635
14636 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14637 }
14638
14639
14640
14641
14642
14643
14644
14645 int
14646 get_tab_bar_item_kbd (struct frame *f, int x, int y, int *prop_idx,
14647 bool *close_p)
14648 {
14649 struct window *w;
14650 int area, vpos, hpos;
14651 struct glyph *glyph;
14652
14653 w = XWINDOW (f->tab_bar_window);
14654
14655
14656 frame_to_window_pixel_xy (w, &x, &y);
14657
14658
14659 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, 0,
14660 0, &area);
14661 if (glyph == NULL)
14662 return -1;
14663
14664
14665
14666 if (!tab_bar_item_info (f, glyph, prop_idx, close_p))
14667 return -1;
14668
14669 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14670 }
14671
14672
14673
14674
14675
14676
14677
14678 Lisp_Object
14679 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14680 int modifiers)
14681 {
14682 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14683 struct window *w = XWINDOW (f->tab_bar_window);
14684 int hpos, vpos, prop_idx;
14685 bool close_p;
14686 struct glyph *glyph;
14687 Lisp_Object enabled_p;
14688 int ts;
14689
14690 frame_to_window_pixel_xy (w, &x, &y);
14691 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14692 if (ts == -1)
14693 return Fcons (Qtab_bar, Qnil);
14694
14695
14696 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14697 if (NILP (enabled_p))
14698 return Qnil;
14699
14700 if (down_p)
14701 {
14702
14703 if (!NILP (Vmouse_highlight))
14704 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14705 f->last_tab_bar_item = prop_idx;
14706 }
14707 else
14708 {
14709
14710 if (!NILP (Vmouse_highlight))
14711 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14712 f->last_tab_bar_item = -1;
14713 }
14714
14715 Lisp_Object caption =
14716 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14717
14718 AUTO_LIST2 (props, Qmenu_item,
14719 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14720 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14721 close_p ? Qt : Qnil));
14722
14723 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14724 props, caption);
14725
14726 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14727 }
14728
14729
14730
14731
14732
14733
14734 static void
14735 note_tab_bar_highlight (struct frame *f, int x, int y)
14736 {
14737 Lisp_Object window = f->tab_bar_window;
14738 struct window *w = XWINDOW (window);
14739 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14740 int hpos, vpos;
14741 struct glyph *glyph;
14742 struct glyph_row *row;
14743 int i;
14744 Lisp_Object enabled_p;
14745 int prop_idx;
14746 bool close_p;
14747 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14748 int rc;
14749
14750
14751
14752 if (x <= 0 || y <= 0)
14753 {
14754 clear_mouse_face (hlinfo);
14755 return;
14756 }
14757
14758 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14759 if (rc < 0)
14760 {
14761
14762 clear_mouse_face (hlinfo);
14763 return;
14764 }
14765 else if (rc == 0)
14766
14767 goto set_help_echo;
14768
14769 clear_mouse_face (hlinfo);
14770
14771 bool mouse_down_p = false;
14772
14773
14774
14775
14776
14777 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14778 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14779 && f == dpyinfo->last_mouse_frame);
14780
14781 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14782 && f->last_tab_bar_item != -1)
14783 return;
14784 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14785
14786
14787 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14788 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14789 {
14790
14791
14792 row = MATRIX_ROW (w->current_matrix, vpos);
14793 for (i = x = 0; i < hpos; ++i)
14794 x += row->glyphs[TEXT_AREA][i].pixel_width;
14795
14796
14797 hlinfo->mouse_face_beg_col = hpos;
14798 hlinfo->mouse_face_beg_row = vpos;
14799 hlinfo->mouse_face_beg_x = x;
14800 hlinfo->mouse_face_past_end = false;
14801
14802 hlinfo->mouse_face_end_col = hpos + 1;
14803 hlinfo->mouse_face_end_row = vpos;
14804 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14805 hlinfo->mouse_face_window = window;
14806 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14807
14808
14809 show_mouse_face (hlinfo, draw);
14810 }
14811
14812 set_help_echo:
14813
14814
14815
14816 help_echo_object = help_echo_window = Qnil;
14817 help_echo_pos = -1;
14818 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14819 if (NILP (help_echo_string))
14820 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14821 }
14822
14823 #endif
14824
14825
14826 static Lisp_Object
14827 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14828 {
14829 ptrdiff_t clen = 0;
14830
14831 for (int i = 0; i < f->n_tab_bar_items; i++)
14832 {
14833 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14834 + TAB_BAR_ITEM_CAPTION));
14835 if (NILP (caption))
14836 return Qnil;
14837 clen += SCHARS (caption);
14838 if (x < clen)
14839 {
14840 *prop_idx = i;
14841 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14842 - (clen - x)),
14843 Qclose_tab,
14844 caption));
14845 return caption;
14846 }
14847 }
14848 return Qnil;
14849 }
14850
14851
14852
14853
14854
14855
14856 Lisp_Object
14857 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14858 struct input_event *event)
14859 {
14860
14861 if (y < FRAME_MENU_BAR_LINES (f)
14862 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14863 return Qnil;
14864
14865
14866 int prop_idx;
14867 bool close_p;
14868 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14869
14870 if (NILP (caption))
14871 return Qnil;
14872
14873 if (NILP (AREF (f->tab_bar_items,
14874 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14875 return Qnil;
14876
14877 if (down_p)
14878 f->last_tab_bar_item = prop_idx;
14879 else
14880 f->last_tab_bar_item = -1;
14881
14882 caption = Fcopy_sequence (caption);
14883
14884 AUTO_LIST2 (props, Qmenu_item,
14885 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14886 + TAB_BAR_ITEM_KEY),
14887 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14888 + TAB_BAR_ITEM_BINDING),
14889 close_p ? Qt : Qnil));
14890
14891 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14892 props, caption);
14893
14894 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14895 }
14896
14897
14898
14899
14900
14901
14902
14903 #ifdef HAVE_WINDOW_SYSTEM
14904
14905
14906
14907
14908
14909
14910 static void
14911 update_tool_bar (struct frame *f, bool save_match_data)
14912 {
14913 #ifdef HAVE_EXT_TOOL_BAR
14914 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14915 #else
14916 bool do_update = (WINDOWP (f->tool_bar_window)
14917 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14918 #endif
14919
14920 if (do_update)
14921 {
14922 Lisp_Object window;
14923 struct window *w;
14924
14925 window = FRAME_SELECTED_WINDOW (f);
14926 w = XWINDOW (window);
14927
14928
14929
14930
14931
14932
14933
14934
14935 if (windows_or_buffers_changed
14936 || w->update_mode_line
14937 || update_mode_lines
14938 || window_buffer_changed (w))
14939 {
14940 struct buffer *prev = current_buffer;
14941 specpdl_ref count = SPECPDL_INDEX ();
14942 Lisp_Object frame, new_tool_bar;
14943 int new_n_tool_bar;
14944
14945
14946
14947
14948 set_buffer_internal_1 (XBUFFER (w->contents));
14949
14950
14951 if (save_match_data)
14952 record_unwind_save_match_data ();
14953
14954
14955 if (NILP (Voverriding_local_map_menu_flag))
14956 {
14957 specbind (Qoverriding_terminal_local_map, Qnil);
14958 specbind (Qoverriding_local_map, Qnil);
14959 }
14960
14961
14962
14963
14964
14965 eassert (EQ (selected_window,
14966
14967
14968 XFRAME (selected_frame)->selected_window));
14969 record_unwind_protect (restore_selected_window, selected_window);
14970 XSETFRAME (frame, f);
14971 selected_frame = frame;
14972 selected_window = FRAME_SELECTED_WINDOW (f);
14973
14974
14975 new_tool_bar
14976 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
14977 &new_n_tool_bar);
14978
14979
14980 if (new_n_tool_bar != f->n_tool_bar_items
14981 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
14982 {
14983
14984
14985
14986 block_input ();
14987 fset_tool_bar_items (f, new_tool_bar);
14988 f->n_tool_bar_items = new_n_tool_bar;
14989 w->update_mode_line = true;
14990 unblock_input ();
14991 }
14992
14993 unbind_to (count, Qnil);
14994 set_buffer_internal_1 (prev);
14995 }
14996 }
14997 }
14998
14999 #ifndef HAVE_EXT_TOOL_BAR
15000
15001
15002
15003
15004
15005
15006
15007
15008 static void
15009 build_desired_tool_bar_string (struct frame *f)
15010 {
15011 int i, size, size_needed;
15012 Lisp_Object image, plist;
15013
15014 image = plist = Qnil;
15015
15016
15017
15018
15019
15020 size = (STRINGP (f->desired_tool_bar_string)
15021 ? SCHARS (f->desired_tool_bar_string)
15022 : 0);
15023
15024
15025 size_needed = f->n_tool_bar_items;
15026
15027
15028
15029 if (size < size_needed || NILP (f->desired_tool_bar_string))
15030
15031
15032 fset_desired_tool_bar_string (f, make_uninit_string (size_needed));
15033 else
15034 {
15035 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
15036 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
15037 props, f->desired_tool_bar_string);
15038 }
15039
15040 f->tool_bar_wraps_p = false;
15041
15042
15043
15044
15045 for (i = 0; i < f->n_tool_bar_items; ++i)
15046 {
15047 #define PROP(IDX) \
15048 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
15049
15050 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
15051 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
15052 int hmargin, vmargin, relief, idx, end;
15053
15054 if (!NILP (PROP (TOOL_BAR_ITEM_WRAP)))
15055 {
15056
15057
15058 SSET (f->desired_tool_bar_string, i, '\n');
15059
15060
15061
15062 f->tool_bar_wraps_p = true;
15063 continue;
15064 }
15065
15066
15067 SSET (f->desired_tool_bar_string, i, ' ');
15068
15069
15070
15071 image = PROP (TOOL_BAR_ITEM_IMAGES);
15072 if (VECTORP (image))
15073 {
15074 if (enabled_p)
15075 idx = (selected_p
15076 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
15077 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
15078 else
15079 idx = (selected_p
15080 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15081 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15082
15083 eassert (ASIZE (image) >= idx);
15084 image = AREF (image, idx);
15085 }
15086 else
15087 idx = -1;
15088
15089
15090 if (!valid_image_p (image))
15091 continue;
15092
15093
15094 plist = Fcopy_sequence (XCDR (image));
15095
15096
15097 relief = (tool_bar_button_relief >= 0
15098 ? min (tool_bar_button_relief,
15099 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15100 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15101 hmargin = vmargin = relief;
15102
15103 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15104 INT_MAX - max (hmargin, vmargin)))
15105 {
15106 hmargin += XFIXNAT (Vtool_bar_button_margin);
15107 vmargin += XFIXNAT (Vtool_bar_button_margin);
15108 }
15109 else if (CONSP (Vtool_bar_button_margin))
15110 {
15111 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15112 INT_MAX - hmargin))
15113 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15114
15115 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15116 INT_MAX - vmargin))
15117 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15118 }
15119
15120 if (auto_raise_tool_bar_buttons_p)
15121 {
15122
15123
15124 if (selected_p)
15125 {
15126 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15127 hmargin -= relief;
15128 vmargin -= relief;
15129 }
15130 }
15131 else
15132 {
15133
15134
15135
15136 plist = plist_put (plist, QCrelief,
15137 (selected_p
15138 ? make_fixnum (-relief)
15139 : make_fixnum (relief)));
15140 hmargin -= relief;
15141 vmargin -= relief;
15142 }
15143
15144
15145 if (hmargin || vmargin)
15146 {
15147 if (hmargin == vmargin)
15148 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15149 else
15150 plist = plist_put (plist, QCmargin,
15151 Fcons (make_fixnum (hmargin),
15152 make_fixnum (vmargin)));
15153 }
15154
15155
15156
15157
15158 if (!enabled_p && idx < 0)
15159 plist = plist_put (plist, QCconversion, Qdisabled);
15160
15161
15162
15163
15164
15165 image = Fcons (Qimage, plist);
15166 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15167 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15168
15169
15170
15171
15172 if (i + 1 == f->n_tool_bar_items)
15173 end = SCHARS (f->desired_tool_bar_string);
15174 else
15175 end = i + 1;
15176 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15177 props, f->desired_tool_bar_string);
15178 #undef PROP
15179 }
15180
15181
15182
15183
15184
15185
15186
15187 for (; i < size; ++i)
15188
15189 SSET (f->desired_tool_bar_string, i, ' ');
15190 }
15191
15192
15193
15194
15195
15196
15197
15198
15199
15200
15201
15202
15203
15204
15205
15206
15207
15208 static void
15209 display_tool_bar_line (struct it *it, int height)
15210 {
15211 struct glyph_row *row = it->glyph_row;
15212 int max_x = it->last_visible_x;
15213 struct glyph *last;
15214
15215
15216 clear_glyph_row (row);
15217 row->enabled_p = true;
15218 row->y = it->current_y;
15219
15220
15221
15222 it->start_of_box_run_p = true;
15223
15224 while (it->current_x < max_x)
15225 {
15226 int x, n_glyphs_before, i, nglyphs;
15227 struct it it_before;
15228
15229
15230 if (!get_next_display_element (it))
15231 {
15232
15233 if (height < 0 && !it->hpos)
15234 return;
15235 break;
15236 }
15237
15238
15239 n_glyphs_before = row->used[TEXT_AREA];
15240 it_before = *it;
15241
15242 PRODUCE_GLYPHS (it);
15243
15244 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15245 i = 0;
15246 x = it_before.current_x;
15247 while (i < nglyphs)
15248 {
15249 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15250
15251 if (x + glyph->pixel_width > max_x)
15252 {
15253
15254 row->used[TEXT_AREA] = n_glyphs_before;
15255 *it = it_before;
15256
15257
15258
15259 if (n_glyphs_before == 0
15260 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15261 break;
15262 goto out;
15263 }
15264
15265 ++it->hpos;
15266 x += glyph->pixel_width;
15267 ++i;
15268 }
15269
15270
15271
15272
15273
15274
15275 if (ITERATOR_AT_END_OF_LINE_P (it))
15276 {
15277 reseat_at_next_visible_line_start (it, false);
15278 break;
15279 }
15280
15281 if (ITERATOR_AT_END_P (it))
15282 break;
15283
15284 set_iterator_to_next (it, true);
15285 }
15286
15287 out:;
15288
15289 row->displays_text_p = row->used[TEXT_AREA] != 0;
15290
15291
15292
15293
15294
15295
15296
15297 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15298 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15299 it->face_id = DEFAULT_FACE_ID;
15300
15301 extend_face_to_end_of_line (it);
15302 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15303 last->right_box_line_p = true;
15304 if (last == row->glyphs[TEXT_AREA])
15305 last->left_box_line_p = true;
15306
15307
15308 if (height != -1
15309 && (height -= it->max_ascent + it->max_descent) > 0)
15310 {
15311
15312 height %= FRAME_LINE_HEIGHT (it->f);
15313 it->max_ascent += height / 2;
15314 it->max_descent += (height + 1) / 2;
15315 }
15316
15317 compute_line_metrics (it);
15318
15319
15320 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15321 {
15322 row->height = row->phys_height = it->last_visible_y - row->y;
15323 row->visible_height = row->height;
15324 row->ascent = row->phys_ascent = 0;
15325 row->extra_line_spacing = 0;
15326 }
15327
15328 row->full_width_p = true;
15329 row->continued_p = false;
15330 row->truncated_on_left_p = false;
15331 row->truncated_on_right_p = false;
15332
15333 it->current_x = it->hpos = 0;
15334 it->current_y += row->height;
15335 ++it->vpos;
15336 ++it->glyph_row;
15337 }
15338
15339
15340
15341
15342
15343
15344 static int
15345 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15346 {
15347 struct window *w = XWINDOW (f->tool_bar_window);
15348 struct it it;
15349
15350
15351
15352 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15353
15354
15355
15356 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15357 temp_row->reversed_p = false;
15358 it.first_visible_x = 0;
15359 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15360 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15361 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15362 it.paragraph_embedding = L2R;
15363
15364 while (!ITERATOR_AT_END_P (&it))
15365 {
15366 clear_glyph_row (temp_row);
15367 it.glyph_row = temp_row;
15368 display_tool_bar_line (&it, -1);
15369 }
15370 clear_glyph_row (temp_row);
15371
15372
15373 if (n_rows)
15374 *n_rows = it.vpos > 0 ? it.vpos : -1;
15375
15376 if (pixelwise)
15377 return it.current_y;
15378 else
15379 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15380 }
15381
15382 #endif
15383
15384 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15385 0, 2, 0,
15386 doc:
15387
15388 )
15389 (Lisp_Object frame, Lisp_Object pixelwise)
15390 {
15391 int height = 0;
15392
15393 #ifndef HAVE_EXT_TOOL_BAR
15394 struct frame *f = decode_any_frame (frame);
15395
15396 if (WINDOWP (f->tool_bar_window)
15397 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15398 {
15399 update_tool_bar (f, true);
15400 if (f->n_tool_bar_items)
15401 {
15402 build_desired_tool_bar_string (f);
15403 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15404 }
15405 }
15406 #endif
15407
15408 return make_fixnum (height);
15409 }
15410
15411 #ifndef HAVE_EXT_TOOL_BAR
15412
15413
15414
15415 static bool
15416 redisplay_tool_bar (struct frame *f)
15417 {
15418 struct window *w;
15419 struct it it;
15420 struct glyph_row *row;
15421 bool change_height_p;
15422
15423 change_height_p = false;
15424 f->tool_bar_redisplayed = true;
15425
15426
15427
15428
15429
15430 if (!WINDOWP (f->tool_bar_window)
15431 || (w = XWINDOW (f->tool_bar_window),
15432 WINDOW_TOTAL_LINES (w) == 0))
15433 {
15434
15435
15436
15437
15438
15439 f->tool_bar_resized = true;
15440
15441 return false;
15442 }
15443
15444
15445 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15446 it.first_visible_x = 0;
15447 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15448 row = it.glyph_row;
15449 row->reversed_p = false;
15450
15451
15452 build_desired_tool_bar_string (f);
15453 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15454 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15455
15456
15457
15458
15459
15460
15461
15462 it.paragraph_embedding = L2R;
15463
15464 if (f->n_tool_bar_rows == 0)
15465 {
15466 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15467
15468 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15469 {
15470 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15471 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15472 frame_default_tool_bar_height = new_height;
15473
15474 clear_glyph_matrix (w->desired_matrix);
15475 f->fonts_changed = true;
15476
15477
15478
15479
15480
15481
15482
15483 resize_frame_windows (f, FRAME_INNER_HEIGHT (f), false);
15484
15485 return true;
15486 }
15487 }
15488
15489
15490
15491 if (f->n_tool_bar_rows > 0)
15492 {
15493 int border, rows, height, extra;
15494
15495 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15496 border = XFIXNUM (Vtool_bar_border);
15497 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15498 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15499 else if (EQ (Vtool_bar_border, Qborder_width))
15500 border = f->border_width;
15501 else
15502 border = 0;
15503 if (border < 0)
15504 border = 0;
15505
15506 rows = f->n_tool_bar_rows;
15507
15508 if (f->tool_bar_wraps_p)
15509 {
15510
15511
15512
15513 while (!ITERATOR_AT_END_P (&it))
15514 display_tool_bar_line (&it, -1);
15515
15516
15517
15518
15519
15520
15521 if (it.current_y != it.last_visible_y)
15522 change_height_p = true;
15523 }
15524 else
15525 {
15526 height = max (1, (it.last_visible_y - border) / rows);
15527 extra = it.last_visible_y - border - height * rows;
15528
15529 while (it.current_y < it.last_visible_y)
15530 {
15531 int h = 0;
15532 if (extra > 0 && rows-- > 0)
15533 {
15534 h = (extra + rows - 1) / rows;
15535 extra -= h;
15536 }
15537
15538 display_tool_bar_line (&it, height + h);
15539 }
15540 }
15541 }
15542 else
15543 {
15544 while (it.current_y < it.last_visible_y)
15545 display_tool_bar_line (&it, 0);
15546 }
15547
15548
15549
15550 w->desired_matrix->no_scrolling_p = true;
15551 w->must_be_updated_p = true;
15552
15553 if (!NILP (Vauto_resize_tool_bars))
15554 {
15555
15556
15557 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15558 change_height_p = true;
15559
15560
15561
15562
15563
15564 row = it.glyph_row - 1;
15565
15566
15567
15568
15569 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15570 && row->height >= FRAME_LINE_HEIGHT (f))
15571 change_height_p = true;
15572
15573
15574
15575 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15576 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15577 change_height_p = true;
15578
15579
15580
15581 if (change_height_p)
15582 {
15583 int nrows;
15584 int new_height = tool_bar_height (f, &nrows, true);
15585
15586 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15587 && !f->minimize_tool_bar_window_p)
15588 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15589 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15590 f->minimize_tool_bar_window_p = false;
15591
15592 if (change_height_p)
15593 {
15594 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15595 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15596 frame_default_tool_bar_height = new_height;
15597 clear_glyph_matrix (w->desired_matrix);
15598 f->n_tool_bar_rows = nrows;
15599 f->fonts_changed = true;
15600
15601 return true;
15602 }
15603 }
15604 }
15605
15606 f->minimize_tool_bar_window_p = false;
15607
15608 return false;
15609 }
15610
15611
15612
15613
15614
15615
15616 static bool
15617 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15618 {
15619 Lisp_Object prop;
15620 ptrdiff_t charpos;
15621
15622
15623
15624
15625 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15626 charpos = max (0, charpos);
15627
15628
15629
15630
15631 prop = Fget_text_property (make_fixnum (charpos),
15632 Qmenu_item, f->current_tool_bar_string);
15633 if (! FIXNUMP (prop))
15634 return false;
15635 *prop_idx = XFIXNUM (prop);
15636 return true;
15637 }
15638
15639
15640
15641
15642
15643
15644
15645
15646
15647
15648
15649
15650 static int
15651 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15652 int *hpos, int *vpos, int *prop_idx)
15653 {
15654 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15655 struct window *w = XWINDOW (f->tool_bar_window);
15656 int area;
15657
15658
15659 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15660 if (*glyph == NULL)
15661 return -1;
15662
15663
15664
15665 if (!tool_bar_item_info (f, *glyph, prop_idx))
15666 return -1;
15667
15668
15669 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15670 && *vpos >= hlinfo->mouse_face_beg_row
15671 && *vpos <= hlinfo->mouse_face_end_row
15672 && (*vpos > hlinfo->mouse_face_beg_row
15673 || *hpos >= hlinfo->mouse_face_beg_col)
15674 && (*vpos < hlinfo->mouse_face_end_row
15675 || *hpos < hlinfo->mouse_face_end_col
15676 || hlinfo->mouse_face_past_end))
15677 return 0;
15678
15679 return 1;
15680 }
15681
15682
15683
15684
15685
15686
15687
15688
15689 void
15690 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15691 int modifiers, Lisp_Object device)
15692 {
15693 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15694 struct window *w = XWINDOW (f->tool_bar_window);
15695 int hpos, vpos, prop_idx;
15696 struct glyph *glyph;
15697 Lisp_Object enabled_p;
15698 int ts;
15699
15700
15701
15702
15703
15704
15705
15706
15707 frame_to_window_pixel_xy (w, &x, &y);
15708 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15709 if (ts == -1
15710 || (ts != 0 && !NILP (Vmouse_highlight)))
15711 return;
15712
15713
15714
15715
15716 if (NILP (Vmouse_highlight) && !down_p)
15717 prop_idx = f->last_tool_bar_item;
15718
15719
15720 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15721 if (NILP (enabled_p))
15722 return;
15723
15724 if (down_p)
15725 {
15726
15727 if (!NILP (Vmouse_highlight))
15728 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15729 f->last_tool_bar_item = prop_idx;
15730 }
15731 else
15732 {
15733 Lisp_Object key, frame;
15734 struct input_event event;
15735 EVENT_INIT (event);
15736
15737
15738 if (!NILP (Vmouse_highlight))
15739 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15740
15741 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15742
15743 XSETFRAME (frame, f);
15744 event.kind = TOOL_BAR_EVENT;
15745 event.frame_or_window = frame;
15746 event.arg = key;
15747 event.modifiers = modifiers;
15748 event.device = device;
15749 kbd_buffer_store_event (&event);
15750 f->last_tool_bar_item = -1;
15751 }
15752 }
15753
15754 void
15755 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15756 int modifiers)
15757 {
15758 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15759 }
15760
15761
15762
15763
15764
15765 static void
15766 note_tool_bar_highlight (struct frame *f, int x, int y)
15767 {
15768 Lisp_Object window = f->tool_bar_window;
15769 struct window *w = XWINDOW (window);
15770 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15771 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15772 int hpos, vpos;
15773 struct glyph *glyph;
15774 struct glyph_row *row;
15775 int i;
15776 Lisp_Object enabled_p;
15777 int prop_idx;
15778 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15779 bool mouse_down_p;
15780 int rc;
15781
15782
15783
15784 if (x <= 0 || y <= 0)
15785 {
15786 clear_mouse_face (hlinfo);
15787 return;
15788 }
15789
15790 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15791 if (rc < 0)
15792 {
15793
15794 clear_mouse_face (hlinfo);
15795 return;
15796 }
15797 else if (rc == 0)
15798
15799 goto set_help_echo;
15800
15801 clear_mouse_face (hlinfo);
15802
15803
15804 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15805 && f == dpyinfo->last_mouse_frame);
15806
15807 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15808 return;
15809
15810 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15811
15812
15813 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15814 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15815 {
15816
15817
15818 row = MATRIX_ROW (w->current_matrix, vpos);
15819 for (i = x = 0; i < hpos; ++i)
15820 x += row->glyphs[TEXT_AREA][i].pixel_width;
15821
15822
15823 hlinfo->mouse_face_beg_col = hpos;
15824 hlinfo->mouse_face_beg_row = vpos;
15825 hlinfo->mouse_face_beg_x = x;
15826 hlinfo->mouse_face_past_end = false;
15827
15828 hlinfo->mouse_face_end_col = hpos + 1;
15829 hlinfo->mouse_face_end_row = vpos;
15830 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15831 hlinfo->mouse_face_window = window;
15832 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15833
15834
15835 show_mouse_face (hlinfo, draw);
15836 }
15837
15838 set_help_echo:
15839
15840
15841
15842 help_echo_object = help_echo_window = Qnil;
15843 help_echo_pos = -1;
15844 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15845 if (NILP (help_echo_string))
15846 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15847 }
15848
15849 #endif
15850
15851 #endif
15852
15853
15854
15855
15856
15857
15858
15859
15860
15861
15862
15863
15864
15865 static bool
15866 hscroll_window_tree (Lisp_Object window)
15867 {
15868 bool hscrolled_p = false;
15869 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15870 int hscroll_step_abs = 0;
15871 double hscroll_step_rel = 0;
15872
15873 if (hscroll_relative_p)
15874 {
15875 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15876 if (hscroll_step_rel < 0)
15877 {
15878 hscroll_relative_p = false;
15879 hscroll_step_abs = 0;
15880 }
15881 }
15882 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15883 {
15884 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15885 if (hscroll_step_abs < 0)
15886 hscroll_step_abs = 0;
15887 }
15888 else
15889 hscroll_step_abs = 0;
15890
15891 while (WINDOWP (window))
15892 {
15893 struct window *w = XWINDOW (window);
15894
15895 if (WINDOWP (w->contents))
15896 hscrolled_p |= hscroll_window_tree (w->contents);
15897 else if (w->cursor.vpos >= 0
15898
15899
15900
15901
15902
15903
15904 && !(w == XWINDOW (echo_area_window)
15905 && !NILP (echo_area_buffer[0])))
15906 {
15907 int h_margin;
15908 int text_area_width;
15909 struct glyph_row *cursor_row;
15910 struct glyph_row *bottom_row;
15911
15912 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15913 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15914 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15915 else
15916 cursor_row = bottom_row - 1;
15917
15918 if (!cursor_row->enabled_p)
15919 {
15920 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15921 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15922 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15923 else
15924 cursor_row = bottom_row - 1;
15925 }
15926 bool row_r2l_p = cursor_row->reversed_p;
15927 bool hscl = hscrolling_current_line_p (w);
15928 int x_offset = 0;
15929
15930
15931 if (!NILP (Vdisplay_line_numbers))
15932 {
15933 struct glyph *g;
15934 if (!row_r2l_p)
15935 {
15936 for (g = cursor_row->glyphs[TEXT_AREA];
15937 g < cursor_row->glyphs[TEXT_AREA]
15938 + cursor_row->used[TEXT_AREA];
15939 g++)
15940 {
15941 if (!(NILP (g->object) && g->charpos < 0))
15942 break;
15943 x_offset += g->pixel_width;
15944 }
15945 }
15946 else
15947 {
15948 for (g = cursor_row->glyphs[TEXT_AREA]
15949 + cursor_row->used[TEXT_AREA];
15950 g > cursor_row->glyphs[TEXT_AREA];
15951 g--)
15952 {
15953 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
15954 break;
15955 x_offset += (g - 1)->pixel_width;
15956 }
15957 }
15958 }
15959 if (cursor_row->truncated_on_left_p)
15960 {
15961
15962 struct frame *f = XFRAME (WINDOW_FRAME (w));
15963 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
15964 }
15965
15966 text_area_width = window_box_width (w, TEXT_AREA);
15967
15968
15969 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
15970 * WINDOW_FRAME_COLUMN_WIDTH (w));
15971
15972
15973
15974 if (w->suspend_auto_hscroll
15975 && NILP (Fequal (Fwindow_point (window),
15976 Fwindow_old_point (window))))
15977 {
15978 w->suspend_auto_hscroll = false;
15979
15980
15981
15982
15983 if (w->min_hscroll == 0 && w->hscroll > 0
15984 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
15985 Qcurrent_line))
15986 SET_FRAME_GARBAGED (XFRAME (w->frame));
15987 }
15988
15989
15990 Fset_marker (w->old_pointm,
15991 ((w == XWINDOW (selected_window))
15992 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
15993 : Fmarker_position (w->pointm)),
15994 w->contents);
15995
15996 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
15997 && !w->suspend_auto_hscroll
15998
15999
16000
16001
16002
16003
16004 && (CHARPOS (cursor_row->start.pos)
16005 >= BUF_BEG (XBUFFER (w->contents)))
16006
16007
16008
16009
16010 && ((!row_r2l_p
16011 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
16012 || (cursor_row->enabled_p
16013 && cursor_row->truncated_on_right_p
16014 && (w->cursor.x >= text_area_width - h_margin))))
16015
16016
16017
16018
16019
16020
16021 || (row_r2l_p
16022 && ((cursor_row->enabled_p
16023
16024
16025
16026 && cursor_row->truncated_on_right_p
16027 && w->cursor.x <= h_margin)
16028 || (w->hscroll
16029 && (w->cursor.x >= (text_area_width - h_margin
16030 - x_offset)))))
16031
16032
16033
16034
16035
16036 || (hscl
16037 && w->hscroll != w->min_hscroll
16038 && !cursor_row->truncated_on_left_p)))
16039 {
16040 struct it it;
16041 ptrdiff_t hscroll;
16042 struct buffer *saved_current_buffer;
16043 ptrdiff_t pt;
16044 int wanted_x;
16045
16046
16047 saved_current_buffer = current_buffer;
16048 current_buffer = XBUFFER (w->contents);
16049
16050 if (w == XWINDOW (selected_window))
16051 pt = PT;
16052 else
16053 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
16054
16055
16056
16057 init_to_row_start (&it, w, cursor_row);
16058 if (hscl)
16059 it.first_visible_x = window_hscroll_limited (w, it.f)
16060 * FRAME_COLUMN_WIDTH (it.f);
16061 it.last_visible_x = DISP_INFINITY;
16062
16063 ptrdiff_t nchars = pt - IT_CHARPOS (it);
16064 if (current_buffer->long_line_optimizations_p
16065 && nchars > large_hscroll_threshold)
16066 {
16067
16068
16069
16070
16071 fast_move_it_horizontally (&it, nchars);
16072 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
16073 }
16074 else
16075 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
16076
16077
16078
16079
16080
16081
16082 if (it.method == GET_FROM_STRING && pt > 1)
16083 {
16084 init_to_row_start (&it, w, cursor_row);
16085 if (hscl)
16086 it.first_visible_x = (window_hscroll_limited (w, it.f)
16087 * FRAME_COLUMN_WIDTH (it.f));
16088 if (current_buffer->long_line_optimizations_p
16089 && nchars > large_hscroll_threshold)
16090 {
16091 fast_move_it_horizontally (&it, nchars - 1);
16092 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
16093 }
16094 else
16095 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
16096 }
16097 current_buffer = saved_current_buffer;
16098
16099
16100 if (!hscroll_relative_p && hscroll_step_abs == 0)
16101 hscroll = max (0, (it.current_x
16102 - (ITERATOR_AT_END_OF_LINE_P (&it)
16103 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
16104 : (text_area_width / 2))))
16105 / FRAME_COLUMN_WIDTH (it.f);
16106 else if ((!row_r2l_p
16107 && w->cursor.x >= text_area_width - h_margin)
16108 || (row_r2l_p && w->cursor.x <= h_margin))
16109 {
16110 if (hscroll_relative_p)
16111 wanted_x = text_area_width * (1 - hscroll_step_rel)
16112 - h_margin;
16113 else
16114 wanted_x = text_area_width
16115 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16116 - h_margin;
16117 hscroll
16118 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16119 }
16120 else
16121 {
16122 if (hscroll_relative_p)
16123 wanted_x =
16124 text_area_width * hscroll_step_rel + h_margin + x_offset;
16125 else
16126 wanted_x =
16127 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16128 + h_margin + x_offset;
16129 hscroll
16130 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16131 }
16132 hscroll = max (hscroll, w->min_hscroll);
16133
16134
16135
16136
16137 if (w->hscroll != hscroll
16138
16139
16140
16141
16142 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16143 {
16144 struct buffer *b = XBUFFER (w->contents);
16145 b->prevent_redisplay_optimizations_p = true;
16146 w->hscroll = hscroll;
16147 hscrolled_p = true;
16148 }
16149 }
16150 }
16151
16152 window = w->next;
16153 }
16154
16155
16156 return hscrolled_p;
16157 }
16158
16159
16160
16161
16162
16163
16164
16165
16166 static bool
16167 hscroll_windows (Lisp_Object window)
16168 {
16169 bool hscrolled_p = hscroll_window_tree (window);
16170 if (hscrolled_p)
16171 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16172 return hscrolled_p;
16173 }
16174
16175
16176
16177
16178
16179
16180
16181
16182
16183
16184 #ifdef GLYPH_DEBUG
16185
16186
16187
16188 static int debug_first_unchanged_at_end_vpos;
16189 static int debug_last_unchanged_at_beg_vpos;
16190
16191
16192
16193 static int debug_dvpos, debug_dy;
16194
16195
16196
16197 static ptrdiff_t debug_delta, debug_delta_bytes;
16198
16199
16200
16201
16202 static ptrdiff_t debug_end_vpos;
16203
16204
16205
16206
16207
16208 static void debug_method_add (struct window *, char const *, ...)
16209 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16210
16211 static void
16212 debug_method_add (struct window *w, char const *fmt, ...)
16213 {
16214 void *ptr = w;
16215 char *method = w->desired_matrix->method;
16216 int len = strlen (method);
16217 int size = sizeof w->desired_matrix->method;
16218 int remaining = size - len - 1;
16219 va_list ap;
16220
16221 if (len && remaining)
16222 {
16223 method[len] = '|';
16224 --remaining, ++len;
16225 }
16226
16227 va_start (ap, fmt);
16228 vsnprintf (method + len, remaining + 1, fmt, ap);
16229 va_end (ap);
16230
16231 if (trace_redisplay_p)
16232 fprintf (stderr, "%p (%s): %s\n",
16233 ptr,
16234 ((BUFFERP (w->contents)
16235 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16236 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16237 : "no buffer"),
16238 method + len);
16239 }
16240
16241 #endif
16242
16243
16244
16245
16246
16247
16248
16249 static bool
16250 text_outside_line_unchanged_p (struct window *w,
16251 ptrdiff_t start, ptrdiff_t end)
16252 {
16253 bool unchanged_p = true;
16254
16255
16256 if (window_outdated (w))
16257 {
16258
16259 if (GPT < start || Z - GPT < end)
16260 unchanged_p = false;
16261
16262
16263 if (unchanged_p
16264 && (BEG_UNCHANGED < start - 1
16265 || END_UNCHANGED < end))
16266 unchanged_p = false;
16267
16268
16269
16270 if (unchanged_p
16271 && FIXNUMP (BVAR (current_buffer, selective_display))
16272 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16273 && (BEG_UNCHANGED < start || GPT <= start))
16274 unchanged_p = false;
16275
16276
16277
16278
16279
16280
16281
16282
16283 if (unchanged_p)
16284 {
16285 if (BEG + BEG_UNCHANGED == start
16286 && overlay_touches_p (start))
16287 unchanged_p = false;
16288 if (END_UNCHANGED == end
16289 && overlay_touches_p (Z - end))
16290 unchanged_p = false;
16291 }
16292
16293
16294
16295
16296
16297
16298
16299
16300 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16301 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16302 unchanged_p = false;
16303 }
16304
16305 return unchanged_p;
16306 }
16307
16308
16309
16310
16311
16312
16313
16314
16315
16316 void
16317 redisplay (void)
16318 {
16319 redisplay_internal ();
16320 }
16321
16322
16323 static Lisp_Object
16324 overlay_arrow_string_or_property (Lisp_Object var)
16325 {
16326 Lisp_Object val;
16327
16328 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16329 return val;
16330
16331 return Voverlay_arrow_string;
16332 }
16333
16334
16335 static bool
16336 overlay_arrow_in_current_buffer_p (void)
16337 {
16338 Lisp_Object vlist;
16339
16340 for (vlist = Voverlay_arrow_variable_list;
16341 CONSP (vlist);
16342 vlist = XCDR (vlist))
16343 {
16344 Lisp_Object var = XCAR (vlist);
16345 Lisp_Object val;
16346
16347 if (!SYMBOLP (var))
16348 continue;
16349 val = find_symbol_value (var);
16350 if (MARKERP (val)
16351 && current_buffer == XMARKER (val)->buffer)
16352 return true;
16353 }
16354 return false;
16355 }
16356
16357
16358
16359
16360
16361
16362
16363 static bool
16364 overlay_arrows_changed_p (bool set_redisplay)
16365 {
16366 Lisp_Object vlist;
16367 bool changed = false;
16368
16369 for (vlist = Voverlay_arrow_variable_list;
16370 CONSP (vlist);
16371 vlist = XCDR (vlist))
16372 {
16373 Lisp_Object var = XCAR (vlist);
16374 Lisp_Object val, pstr;
16375
16376 if (!SYMBOLP (var))
16377 continue;
16378 val = find_symbol_value (var);
16379 if (!MARKERP (val))
16380 continue;
16381 if (! EQ (Fmarker_position (val),
16382
16383
16384 Fget (var, Qlast_arrow_position))
16385 || ! (pstr = overlay_arrow_string_or_property (var),
16386 EQ (pstr, Fget (var, Qlast_arrow_string))))
16387 {
16388 struct buffer *buf = XMARKER (val)->buffer;
16389
16390 if (set_redisplay)
16391 {
16392 if (buf)
16393 bset_redisplay (buf);
16394 changed = true;
16395 }
16396 else
16397 return true;
16398 }
16399 }
16400 return changed;
16401 }
16402
16403
16404
16405 static void
16406 update_overlay_arrows (int up_to_date)
16407 {
16408 Lisp_Object vlist;
16409
16410 for (vlist = Voverlay_arrow_variable_list;
16411 CONSP (vlist);
16412 vlist = XCDR (vlist))
16413 {
16414 Lisp_Object var = XCAR (vlist);
16415
16416 if (!SYMBOLP (var))
16417 continue;
16418
16419 if (up_to_date > 0)
16420 {
16421 Lisp_Object val = find_symbol_value (var);
16422 if (!MARKERP (val))
16423 continue;
16424 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16425 Fput (var, Qlast_arrow_string,
16426 overlay_arrow_string_or_property (var));
16427 }
16428 else if (up_to_date < 0
16429 || !NILP (Fget (var, Qlast_arrow_position)))
16430 {
16431 Fput (var, Qlast_arrow_position, Qt);
16432 Fput (var, Qlast_arrow_string, Qt);
16433 }
16434 }
16435 }
16436
16437
16438
16439
16440
16441
16442 static Lisp_Object
16443 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16444 {
16445 Lisp_Object vlist;
16446
16447 for (vlist = Voverlay_arrow_variable_list;
16448 CONSP (vlist);
16449 vlist = XCDR (vlist))
16450 {
16451 Lisp_Object var = XCAR (vlist);
16452 Lisp_Object val;
16453
16454 if (!SYMBOLP (var))
16455 continue;
16456
16457 val = find_symbol_value (var);
16458
16459 if (MARKERP (val)
16460 && current_buffer == XMARKER (val)->buffer
16461 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16462 {
16463 if (FRAME_WINDOW_P (it->f)
16464
16465
16466 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16467 {
16468 #ifdef HAVE_WINDOW_SYSTEM
16469 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16470 {
16471 int fringe_bitmap = lookup_fringe_bitmap (val);
16472 if (fringe_bitmap != 0)
16473 return make_fixnum (fringe_bitmap);
16474 }
16475 #endif
16476 return make_fixnum (-1);
16477 }
16478 return overlay_arrow_string_or_property (var);
16479 }
16480 }
16481
16482 return Qnil;
16483 }
16484
16485
16486
16487
16488
16489 static bool
16490 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16491 struct buffer *buf, ptrdiff_t pt)
16492 {
16493 ptrdiff_t start, end;
16494 Lisp_Object prop;
16495 Lisp_Object buffer;
16496
16497 XSETBUFFER (buffer, buf);
16498
16499
16500 if (prev_buf == buf)
16501 {
16502 if (prev_pt == pt)
16503
16504 return false;
16505
16506 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16507 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16508 && composition_valid_p (start, end, prop)
16509 && start < prev_pt && end > prev_pt)
16510
16511
16512 return (pt <= start || pt >= end);
16513 }
16514
16515
16516 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16517 && find_composition (pt, -1, &start, &end, &prop, buffer)
16518 && composition_valid_p (start, end, prop)
16519 && start < pt && end > pt);
16520 }
16521
16522
16523
16524 static void
16525 reconsider_clip_changes (struct window *w)
16526 {
16527 struct buffer *b = XBUFFER (w->contents);
16528
16529 if (b->clip_changed
16530 && w->window_end_valid
16531 && w->current_matrix->buffer == b
16532 && w->current_matrix->zv == BUF_ZV (b)
16533 && w->current_matrix->begv == BUF_BEGV (b))
16534 b->clip_changed = false;
16535
16536
16537
16538
16539
16540 if (!b->clip_changed && w->window_end_valid)
16541 {
16542 ptrdiff_t pt = (w == XWINDOW (selected_window)
16543 ? PT : marker_position (w->pointm));
16544
16545 if ((w->current_matrix->buffer != b || pt != w->last_point)
16546 && check_point_in_composition (w->current_matrix->buffer,
16547 w->last_point, b, pt))
16548 b->clip_changed = true;
16549 }
16550 }
16551
16552 static void
16553 propagate_buffer_redisplay (void)
16554 {
16555
16556
16557
16558
16559
16560
16561
16562
16563
16564 Lisp_Object ws = window_list ();
16565 for (; CONSP (ws); ws = XCDR (ws))
16566 {
16567 struct window *thisw = XWINDOW (XCAR (ws));
16568 struct buffer *thisb = XBUFFER (thisw->contents);
16569 if (thisb->text->redisplay)
16570 thisw->redisplay = true;
16571 }
16572 }
16573
16574 #define STOP_POLLING \
16575 do { if (! polling_stopped_here) stop_polling (); \
16576 polling_stopped_here = true; } while (false)
16577
16578 #define RESUME_POLLING \
16579 do { if (polling_stopped_here) start_polling (); \
16580 polling_stopped_here = false; } while (false)
16581
16582
16583
16584
16585 static void
16586 redisplay_internal (void)
16587 {
16588 struct window *w = XWINDOW (selected_window);
16589 struct window *sw;
16590 struct frame *fr;
16591 bool pending;
16592 bool must_finish = false, match_p;
16593 struct text_pos tlbufpos, tlendpos;
16594 int number_of_visible_frames;
16595 struct frame *sf;
16596 bool polling_stopped_here = false;
16597 Lisp_Object tail, frame;
16598
16599
16600
16601
16602 enum { MAX_HSCROLL_RETRIES = 16 };
16603 int hscroll_retries = 0;
16604
16605
16606
16607
16608
16609
16610 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16611 int garbaged_frame_retries = 0;
16612
16613
16614
16615
16616 bool consider_all_windows_p;
16617
16618
16619 bool update_miniwindow_p = false;
16620
16621 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16622
16623
16624
16625
16626 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16627 && redisplay_skip_initial_frame)
16628 || !NILP (Vinhibit_redisplay))
16629 return;
16630
16631
16632
16633
16634 fr = XFRAME (w->frame);
16635 sf = SELECTED_FRAME ();
16636
16637 if (!fr->glyphs_initialized_p)
16638 return;
16639
16640 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16641 if (popup_activated ())
16642 return;
16643 #endif
16644
16645 #if defined (HAVE_HAIKU)
16646 if (popup_activated_p)
16647 return;
16648 #endif
16649
16650
16651 if (redisplaying_p)
16652 return;
16653
16654
16655
16656 specpdl_ref count = SPECPDL_INDEX ();
16657 record_unwind_protect_void (unwind_redisplay);
16658 redisplaying_p = true;
16659 block_buffer_flips ();
16660 specbind (Qinhibit_free_realized_faces, Qnil);
16661
16662
16663 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16664
16665 FOR_EACH_FRAME (tail, frame)
16666 XFRAME (frame)->already_hscrolled_p = false;
16667
16668 reset_outermost_restrictions ();
16669
16670 retry:
16671
16672 sw = w;
16673
16674 pending = false;
16675 forget_escape_and_glyphless_faces ();
16676
16677 inhibit_free_realized_faces = false;
16678
16679
16680
16681
16682 if (face_change)
16683 windows_or_buffers_changed = 47;
16684
16685 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16686 && FRAME_TTY (sf)->previous_frame != sf)
16687 {
16688
16689
16690
16691 SET_FRAME_GARBAGED (sf);
16692 #if !defined DOS_NT && !defined HAVE_ANDROID
16693 set_tty_color_mode (FRAME_TTY (sf), sf);
16694 #endif
16695 FRAME_TTY (sf)->previous_frame = sf;
16696 }
16697
16698
16699
16700
16701 number_of_visible_frames = 0;
16702
16703 FOR_EACH_FRAME (tail, frame)
16704 {
16705 struct frame *f = XFRAME (frame);
16706
16707 if (FRAME_REDISPLAY_P (f))
16708 {
16709 ++number_of_visible_frames;
16710
16711 if (f->fonts_changed)
16712 {
16713 adjust_frame_glyphs (f);
16714
16715
16716
16717
16718
16719
16720 SET_FRAME_GARBAGED (f);
16721 f->fonts_changed = false;
16722 }
16723
16724
16725 if (f != sf && f->cursor_type_changed)
16726 fset_redisplay (f);
16727 }
16728 clear_desired_matrices (f);
16729 }
16730
16731
16732 do_pending_window_change (true);
16733
16734
16735 clear_garbaged_frames ();
16736
16737
16738 if (NILP (Vmemory_full))
16739 prepare_menu_bars ();
16740
16741
16742
16743
16744
16745 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16746 sw = w;
16747
16748 reconsider_clip_changes (w);
16749
16750
16751 match_p = XBUFFER (w->contents) == current_buffer;
16752 if (match_p)
16753 {
16754
16755 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16756 w->update_mode_line = true;
16757
16758 if (mode_line_update_needed (w))
16759 w->update_mode_line = true;
16760
16761
16762
16763
16764 if (current_buffer->clip_changed)
16765 bset_update_mode_line (current_buffer);
16766 }
16767
16768
16769
16770
16771
16772
16773 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16774 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16775 || (message_cleared_p
16776 && minibuf_level == 0
16777
16778
16779 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16780 {
16781 echo_area_display (false);
16782
16783 if (message_cleared_p)
16784 update_miniwindow_p = true;
16785
16786 must_finish = true;
16787
16788
16789
16790
16791
16792 if (!display_last_displayed_message_p)
16793 message_cleared_p = false;
16794 }
16795 else if (EQ (selected_window, minibuf_window)
16796 && (current_buffer->clip_changed || window_outdated (w))
16797 && resize_mini_window (w, false))
16798 {
16799
16800
16801 must_finish = true;
16802
16803
16804
16805
16806 clear_garbaged_frames ();
16807 }
16808
16809 if (!NILP (Vrun_hooks))
16810 run_window_change_functions ();
16811
16812 if (windows_or_buffers_changed && !update_mode_lines)
16813
16814
16815
16816 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16817 ? REDISPLAY_SOME : 32);
16818
16819
16820
16821
16822
16823 overlay_arrows_changed_p (true);
16824
16825 consider_all_windows_p = (update_mode_lines
16826 || windows_or_buffers_changed);
16827
16828 #define AINC(a,i) \
16829 { \
16830 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16831 if (FIXNUMP (entry)) \
16832 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16833 }
16834
16835 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16836 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16837
16838
16839
16840
16841
16842 tlbufpos = this_line_start_pos;
16843 tlendpos = this_line_end_pos;
16844 if (!consider_all_windows_p
16845 && CHARPOS (tlbufpos) > 0
16846 && !w->update_mode_line
16847 && !current_buffer->clip_changed
16848 && !current_buffer->prevent_redisplay_optimizations_p
16849 && FRAME_REDISPLAY_P (XFRAME (w->frame))
16850 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16851 && !XFRAME (w->frame)->cursor_type_changed
16852 && !XFRAME (w->frame)->face_change
16853
16854 && this_line_buffer == current_buffer
16855 && match_p
16856 && !w->force_start
16857 && !w->optional_new_start
16858
16859 && PT >= CHARPOS (tlbufpos)
16860 && PT <= Z - CHARPOS (tlendpos)
16861
16862
16863
16864
16865
16866
16867 && (NILP (Vdisplay_line_numbers)
16868 || EQ (Vdisplay_line_numbers, Qvisual))
16869
16870
16871 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16872 CHARPOS (tlendpos)))
16873 {
16874 if (CHARPOS (tlbufpos) > BEGV
16875 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16876 && (CHARPOS (tlbufpos) == ZV
16877 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16878
16879 goto cancel;
16880 else if (window_outdated (w) || MINI_WINDOW_P (w))
16881 {
16882
16883
16884
16885
16886
16887
16888
16889
16890
16891
16892
16893
16894
16895
16896
16897 struct it it;
16898 int line_height_before = this_line_pixel_height;
16899
16900
16901
16902 start_display (&it, w, tlbufpos);
16903
16904
16905 if (it.current_x != this_line_start_x)
16906 goto cancel;
16907
16908
16909
16910
16911 if (it.sp > 1
16912 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16913 goto cancel;
16914 redisplay_trace ("trying display optimization 1\n");
16915 w->cursor.vpos = -1;
16916 overlay_arrow_seen = false;
16917 it.vpos = this_line_vpos;
16918 it.current_y = this_line_y;
16919 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16920 display_line (&it, -1);
16921
16922
16923
16924 if (w->cursor.vpos >= 0
16925
16926
16927 && CHARPOS (this_line_start_pos)
16928
16929 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16930
16931
16932 && this_line_pixel_height == line_height_before
16933
16934
16935
16936
16937 && !hscrolling_current_line_p (w))
16938 {
16939
16940
16941 if (it.current_y < it.last_visible_y)
16942 {
16943 struct glyph_row *row
16944 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
16945 ptrdiff_t delta, delta_bytes;
16946
16947
16948
16949
16950
16951
16952 delta = (Z
16953 - CHARPOS (tlendpos)
16954 - MATRIX_ROW_START_CHARPOS (row));
16955 delta_bytes = (Z_BYTE
16956 - BYTEPOS (tlendpos)
16957 - MATRIX_ROW_START_BYTEPOS (row));
16958
16959 increment_matrix_positions (w->current_matrix,
16960 this_line_vpos + 1,
16961 w->current_matrix->nrows,
16962 delta, delta_bytes);
16963 }
16964
16965
16966
16967
16968 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
16969 {
16970 if (w->window_end_vpos < this_line_vpos)
16971 w->window_end_vpos = this_line_vpos;
16972 }
16973 else if (w->window_end_vpos == this_line_vpos
16974 && this_line_vpos > 0)
16975 w->window_end_vpos = this_line_vpos - 1;
16976 w->window_end_valid = false;
16977
16978
16979 w->desired_matrix->no_scrolling_p = true;
16980
16981 #ifdef GLYPH_DEBUG
16982 *w->desired_matrix->method = 0;
16983 debug_method_add (w, "optimization 1");
16984 #endif
16985 #ifdef HAVE_WINDOW_SYSTEM
16986 update_window_fringes (w, false);
16987 #endif
16988 goto update;
16989 }
16990 else
16991 goto cancel;
16992 }
16993 else if (
16994 PT == w->last_point
16995
16996
16997
16998
16999 && 0 <= w->cursor.vpos
17000 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
17001 {
17002 if (!must_finish)
17003 {
17004 do_pending_window_change (true);
17005
17006 if (WINDOWP (selected_window)
17007 && (w = XWINDOW (selected_window)) != sw)
17008 goto retry;
17009
17010
17011
17012 if (w->cursor_off_p == w->last_cursor_off_p)
17013 goto end_of_redisplay;
17014 }
17015 goto update;
17016 }
17017
17018
17019 else if (NILP (Vshow_trailing_whitespace)
17020 && !cursor_in_echo_area
17021 && !composition_break_at_point)
17022 {
17023 struct it it;
17024 struct glyph_row *row;
17025
17026
17027
17028
17029 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
17030 NULL, DEFAULT_FACE_ID);
17031 it.current_x = this_line_start_x;
17032 it.current_y = this_line_y;
17033 it.vpos = this_line_vpos;
17034
17035 if (current_buffer->long_line_optimizations_p
17036 && it.line_wrap == TRUNCATE
17037 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
17038 {
17039
17040
17041
17042 reseat_at_next_visible_line_start (&it, false);
17043 if (IT_CHARPOS (it) <= PT)
17044 it.vpos = this_line_vpos + 1;
17045 }
17046 else
17047 {
17048
17049
17050 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
17051 }
17052
17053 if (it.vpos == this_line_vpos
17054 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
17055 row->enabled_p))
17056 {
17057 eassert (this_line_vpos == it.vpos);
17058 eassert (this_line_y == it.current_y);
17059 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
17060 if (cursor_row_fully_visible_p (w, false, true, false))
17061 {
17062 #ifdef GLYPH_DEBUG
17063 *w->desired_matrix->method = 0;
17064 debug_method_add (w, "optimization 3");
17065 #endif
17066 goto update;
17067 }
17068 else
17069 goto cancel;
17070 }
17071 else
17072 goto cancel;
17073 }
17074
17075 cancel:
17076
17077 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
17078 }
17079
17080 CHARPOS (this_line_start_pos) = 0;
17081 ++clear_face_cache_count;
17082 #ifdef HAVE_WINDOW_SYSTEM
17083 ++clear_image_cache_count;
17084 #endif
17085
17086
17087
17088
17089
17090
17091 if (consider_all_windows_p)
17092 {
17093 FOR_EACH_FRAME (tail, frame)
17094 XFRAME (frame)->updated_p = false;
17095
17096 propagate_buffer_redisplay ();
17097
17098 FOR_EACH_FRAME (tail, frame)
17099 {
17100 struct frame *f = XFRAME (frame);
17101
17102
17103
17104 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
17105 && !EQ (FRAME_TTY (f)->top_frame, frame))
17106 continue;
17107
17108 retry_frame:
17109 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
17110 {
17111 bool gcscrollbars
17112
17113 = f->redisplay || !REDISPLAY_SOME_P ();
17114 bool f_redisplay_flag = f->redisplay;
17115
17116
17117
17118
17119 if (!FRAME_LIVE_P (f))
17120 continue;
17121
17122
17123
17124 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
17125 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
17126
17127 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17128 {
17129
17130
17131
17132
17133
17134
17135
17136 f->inhibit_clear_image_cache = true;
17137 redisplay_windows (FRAME_ROOT_WINDOW (f));
17138 }
17139
17140
17141 else if (!REDISPLAY_SOME_P ())
17142 f->redisplay = true;
17143
17144
17145 if (!FRAME_LIVE_P (f))
17146 continue;
17147
17148
17149
17150 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17151 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17152
17153 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17154 {
17155
17156 if (f->fonts_changed)
17157 {
17158 adjust_frame_glyphs (f);
17159
17160
17161
17162 SET_FRAME_GARBAGED (f);
17163 f->fonts_changed = false;
17164 goto retry_frame;
17165 }
17166
17167
17168 if (!f->already_hscrolled_p)
17169 {
17170 f->already_hscrolled_p = true;
17171 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17172 && hscroll_windows (f->root_window))
17173 {
17174 hscroll_retries++;
17175 goto retry_frame;
17176 }
17177 }
17178
17179
17180
17181
17182
17183
17184
17185
17186
17187
17188
17189
17190 if (!f_redisplay_flag && f->redisplay)
17191 goto retry_frame;
17192
17193
17194
17195
17196
17197
17198
17199
17200
17201 if (FRAME_GARBAGED_P (f)
17202 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17203 goto retry;
17204
17205 #ifdef HAVE_WINDOW_SYSTEM
17206 if (FRAME_WINDOW_P (f)
17207 && FRAME_RIF (f)->clear_under_internal_border)
17208 FRAME_RIF (f)->clear_under_internal_border (f);
17209 #endif
17210
17211
17212
17213 if (interrupt_input)
17214 unrequest_sigio ();
17215 STOP_POLLING;
17216
17217 pending |= update_frame (f, false, false);
17218
17219
17220
17221
17222
17223
17224
17225 if (FRAME_GARBAGED_P (f))
17226 {
17227 fset_redisplay (f);
17228 f->garbaged = false;
17229 goto retry_frame;
17230 }
17231 f->cursor_type_changed = false;
17232 f->updated_p = true;
17233 f->inhibit_clear_image_cache = false;
17234 }
17235 }
17236 }
17237
17238 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17239
17240 if (!pending)
17241 {
17242
17243
17244
17245 FOR_EACH_FRAME (tail, frame)
17246 {
17247 struct frame *f = XFRAME (frame);
17248 if (f->updated_p)
17249 {
17250 f->redisplay = false;
17251 f->garbaged = false;
17252 mark_window_display_accurate (f->root_window, true);
17253 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17254 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17255 }
17256 }
17257 }
17258 }
17259 else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17260 {
17261 sf->inhibit_clear_image_cache = true;
17262 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17263
17264
17265 internal_condition_case_1 (redisplay_window_1, selected_window,
17266 list_of_error,
17267 redisplay_window_error);
17268 if (update_miniwindow_p)
17269 {
17270 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17271
17272 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17273 internal_condition_case_1 (redisplay_window_1, mini_window,
17274 list_of_error,
17275 redisplay_window_error);
17276 }
17277
17278
17279
17280 update:
17281
17282
17283
17284 if (sf->fonts_changed || sf->redisplay)
17285 {
17286 if (sf->redisplay)
17287 {
17288
17289
17290
17291
17292
17293
17294 windows_or_buffers_changed = 50;
17295 }
17296 goto retry;
17297 }
17298
17299
17300
17301 inhibit_free_realized_faces = true;
17302
17303
17304
17305
17306 if (interrupt_input)
17307 unrequest_sigio ();
17308 STOP_POLLING;
17309
17310 if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17311 {
17312 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17313 && hscroll_windows (selected_window))
17314 {
17315 hscroll_retries++;
17316 goto retry;
17317 }
17318
17319 XWINDOW (selected_window)->must_be_updated_p = true;
17320 pending = update_frame (sf, false, false);
17321 sf->cursor_type_changed = false;
17322 sf->inhibit_clear_image_cache = false;
17323 }
17324
17325
17326
17327
17328
17329
17330 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17331 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17332
17333 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17334 {
17335 XWINDOW (mini_window)->must_be_updated_p = true;
17336 pending |= update_frame (mini_frame, false, false);
17337 mini_frame->cursor_type_changed = false;
17338 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17339 && hscroll_windows (mini_window))
17340 {
17341 hscroll_retries++;
17342 goto retry;
17343 }
17344 }
17345 }
17346
17347
17348
17349 if (pending)
17350 {
17351
17352
17353
17354 CHARPOS (this_line_start_pos) = 0;
17355
17356
17357 update_overlay_arrows (0);
17358
17359
17360
17361 if (!WINDOW_FULL_WIDTH_P (w)
17362 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17363 update_mode_lines = 36;
17364 }
17365 else
17366 {
17367 if (!consider_all_windows_p)
17368 {
17369
17370
17371 if (XBUFFER (w->contents)->text->redisplay
17372 && buffer_window_count (XBUFFER (w->contents)) > 1)
17373
17374
17375 propagate_buffer_redisplay ();
17376 mark_window_display_accurate_1 (w, true);
17377
17378
17379 update_overlay_arrows (1);
17380
17381 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17382 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17383 }
17384
17385 update_mode_lines = 0;
17386 windows_or_buffers_changed = 0;
17387 }
17388
17389
17390
17391
17392
17393 if (interrupt_input)
17394 request_sigio ();
17395 RESUME_POLLING;
17396
17397
17398
17399
17400
17401
17402
17403 if (!pending)
17404 {
17405 int new_count = 0;
17406
17407 FOR_EACH_FRAME (tail, frame)
17408 {
17409 if (FRAME_REDISPLAY_P (XFRAME (frame)))
17410 new_count++;
17411 }
17412
17413 if (new_count != number_of_visible_frames)
17414 windows_or_buffers_changed = 52;
17415 }
17416
17417
17418 do_pending_window_change (true);
17419
17420
17421
17422 if ((windows_or_buffers_changed && !pending)
17423 || (WINDOWP (selected_window)
17424 && (w = XWINDOW (selected_window)) != sw))
17425 goto retry;
17426
17427
17428
17429
17430
17431
17432
17433 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17434 {
17435 clear_face_cache (false);
17436 clear_face_cache_count = 0;
17437 }
17438
17439 #ifdef HAVE_WINDOW_SYSTEM
17440 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17441 {
17442 clear_image_caches (Qnil);
17443 clear_image_cache_count = 0;
17444 }
17445 #endif
17446
17447 end_of_redisplay:
17448 #ifdef HAVE_NS
17449 ns_set_doc_edited ();
17450 #endif
17451 if (interrupt_input && interrupts_deferred)
17452 request_sigio ();
17453
17454
17455
17456 if (max_redisplay_ticks > 0)
17457 update_redisplay_ticks (0, NULL);
17458
17459 unbind_to (count, Qnil);
17460 RESUME_POLLING;
17461 }
17462
17463 static void
17464 unwind_redisplay_preserve_echo_area (void)
17465 {
17466 unblock_buffer_flips ();
17467 }
17468
17469
17470
17471
17472
17473
17474
17475
17476
17477
17478
17479
17480 void
17481 redisplay_preserve_echo_area (int from_where)
17482 {
17483 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17484
17485 block_input ();
17486 specpdl_ref count = SPECPDL_INDEX ();
17487 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17488 block_buffer_flips ();
17489 unblock_input ();
17490
17491 if (!NILP (echo_area_buffer[1]))
17492 {
17493
17494
17495 display_last_displayed_message_p = true;
17496 redisplay_internal ();
17497 display_last_displayed_message_p = false;
17498 }
17499 else
17500 redisplay_internal ();
17501
17502 flush_frame (SELECTED_FRAME ());
17503 unbind_to (count, Qnil);
17504 }
17505
17506
17507
17508
17509 static void
17510 unwind_redisplay (void)
17511 {
17512 redisplaying_p = false;
17513 unblock_buffer_flips ();
17514 }
17515
17516
17517
17518 void
17519 unwind_display_working_on_window (void)
17520 {
17521 display_working_on_window_p = false;
17522 }
17523
17524
17525
17526
17527
17528
17529 static void
17530 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17531 {
17532 struct buffer *b = XBUFFER (w->contents);
17533 #ifdef HAVE_TEXT_CONVERSION
17534 ptrdiff_t prev_point, prev_mark;
17535 #endif
17536
17537 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17538 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17539 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17540
17541 if (accurate_p)
17542 {
17543 b->clip_changed = false;
17544 b->prevent_redisplay_optimizations_p = false;
17545 eassert (buffer_window_count (b) > 0);
17546
17547
17548
17549 b->text->redisplay = false;
17550
17551 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17552 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17553 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17554 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17555
17556 w->current_matrix->buffer = b;
17557 w->current_matrix->begv = BUF_BEGV (b);
17558 w->current_matrix->zv = BUF_ZV (b);
17559 w->current_matrix->header_line_p = window_wants_header_line (w);
17560 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17561
17562 w->last_cursor_vpos = w->cursor.vpos;
17563 w->last_cursor_off_p = w->cursor_off_p;
17564
17565 #ifdef HAVE_TEXT_CONVERSION
17566 prev_point = w->last_point;
17567 prev_mark = w->last_mark;
17568 #endif
17569
17570 if (w == XWINDOW (selected_window))
17571 w->last_point = BUF_PT (b);
17572 else
17573 w->last_point = marker_position (w->pointm);
17574
17575
17576
17577
17578
17579 if (XMARKER (BVAR (b, mark))->buffer == b
17580 && !NILP (BVAR (b, mark_active)))
17581 w->last_mark = marker_position (BVAR (b, mark));
17582 else
17583 w->last_mark = -1;
17584
17585 #ifdef HAVE_TEXT_CONVERSION
17586
17587 w->ephemeral_last_point = w->last_point;
17588
17589
17590
17591
17592
17593
17594
17595
17596
17597
17598
17599
17600
17601
17602
17603 if ((prev_point != w->last_point
17604 || prev_mark != w->last_mark)
17605 && FRAME_WINDOW_P (WINDOW_XFRAME (w))
17606 && w == XWINDOW (WINDOW_XFRAME (w)->selected_window))
17607 report_point_change (WINDOW_XFRAME (w), w, b);
17608 #endif
17609
17610 w->window_end_valid = true;
17611 w->update_mode_line = false;
17612 w->preserve_vscroll_p = false;
17613 }
17614
17615 w->redisplay = !accurate_p;
17616 }
17617
17618
17619
17620
17621
17622
17623
17624 void
17625 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17626 {
17627 struct window *w;
17628
17629 for (; !NILP (window); window = w->next)
17630 {
17631 w = XWINDOW (window);
17632 if (WINDOWP (w->contents))
17633 mark_window_display_accurate (w->contents, accurate_p);
17634 else
17635 mark_window_display_accurate_1 (w, accurate_p);
17636 }
17637
17638 if (accurate_p)
17639 update_overlay_arrows (1);
17640 else
17641
17642
17643
17644 update_overlay_arrows (-1);
17645 }
17646
17647
17648
17649
17650
17651
17652
17653 Lisp_Object
17654 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17655 {
17656 Lisp_Object val;
17657
17658 if (ASCII_CHAR_P (c))
17659 {
17660 val = dp->ascii;
17661 if (SUB_CHAR_TABLE_P (val))
17662 val = XSUB_CHAR_TABLE (val)->contents[c];
17663 }
17664 else
17665 {
17666 Lisp_Object table;
17667
17668 XSETCHAR_TABLE (table, dp);
17669 val = char_table_ref (table, c);
17670 }
17671 if (NILP (val))
17672 val = dp->defalt;
17673 return val;
17674 }
17675
17676 static int buffer_flip_blocked_depth;
17677
17678 static void
17679 block_buffer_flips (void)
17680 {
17681 eassert (buffer_flip_blocked_depth >= 0);
17682 buffer_flip_blocked_depth++;
17683 }
17684
17685 static void
17686 unblock_buffer_flips (void)
17687 {
17688 eassert (buffer_flip_blocked_depth > 0);
17689 if (--buffer_flip_blocked_depth == 0)
17690 {
17691 Lisp_Object tail, frame;
17692 block_input ();
17693 FOR_EACH_FRAME (tail, frame)
17694 {
17695 struct frame *f = XFRAME (frame);
17696 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17697 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17698 }
17699 unblock_input ();
17700 }
17701 }
17702
17703 bool
17704 buffer_flipping_blocked_p (void)
17705 {
17706 return buffer_flip_blocked_depth > 0;
17707 }
17708
17709
17710
17711
17712
17713
17714
17715
17716 static void
17717 redisplay_windows (Lisp_Object window)
17718 {
17719 while (!NILP (window))
17720 {
17721 struct window *w = XWINDOW (window);
17722
17723 if (WINDOWP (w->contents))
17724 redisplay_windows (w->contents);
17725 else if (BUFFERP (w->contents))
17726 {
17727 displayed_buffer = XBUFFER (w->contents);
17728
17729
17730 internal_condition_case_1 (redisplay_window_0, window,
17731 list_of_error,
17732 redisplay_window_error);
17733 }
17734
17735 window = w->next;
17736 }
17737 }
17738
17739 static Lisp_Object
17740 redisplay_window_error (Lisp_Object error_data)
17741 {
17742 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17743
17744
17745
17746 if (max_redisplay_ticks > 0
17747 && CONSP (error_data)
17748 && EQ (XCAR (error_data), Qerror)
17749 && STRINGP (XCAR (XCDR (error_data))))
17750 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17751 XCAR (XCDR (error_data))),
17752 Vdelayed_warnings_list);
17753 return Qnil;
17754 }
17755
17756 static Lisp_Object
17757 redisplay_window_0 (Lisp_Object window)
17758 {
17759 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17760 redisplay_window (window, false);
17761 return Qnil;
17762 }
17763
17764 static Lisp_Object
17765 redisplay_window_1 (Lisp_Object window)
17766 {
17767 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17768 redisplay_window (window, true);
17769 return Qnil;
17770 }
17771
17772
17773
17774
17775
17776
17777
17778
17779
17780
17781
17782
17783
17784
17785
17786
17787
17788
17789
17790 void
17791 update_redisplay_ticks (int ticks, struct window *w)
17792 {
17793
17794 static struct window *cwindow;
17795 static EMACS_INT window_ticks;
17796
17797
17798
17799
17800 if (!ticks && w != cwindow)
17801 {
17802 cwindow = w;
17803 window_ticks = 0;
17804 }
17805
17806
17807 if ((!w && !redisplaying_p && !display_working_on_window_p)
17808
17809
17810 || (w && MINI_WINDOW_P (w)))
17811 return;
17812
17813 if (ticks > 0)
17814 window_ticks += ticks;
17815 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17816 {
17817
17818
17819
17820 Lisp_Object contents = w ? w->contents : Qnil;
17821 char *bufname =
17822 NILP (contents)
17823 ? SSDATA (BVAR (current_buffer, name))
17824 : (BUFFERP (contents)
17825 ? SSDATA (BVAR (XBUFFER (contents), name))
17826 : (char *) "<unknown>");
17827
17828 windows_or_buffers_changed = 177;
17829
17830
17831
17832 if (w && w->desired_matrix)
17833 w->desired_matrix->no_scrolling_p = true;
17834 error ("Window showing buffer %s takes too long to redisplay", bufname);
17835 }
17836 }
17837
17838
17839
17840
17841
17842
17843
17844
17845
17846
17847 static bool
17848 set_cursor_from_row (struct window *w, struct glyph_row *row,
17849 struct glyph_matrix *matrix,
17850 ptrdiff_t delta, ptrdiff_t delta_bytes,
17851 int dy, int dvpos)
17852 {
17853 struct glyph *glyph = row->glyphs[TEXT_AREA];
17854 struct glyph *end = glyph + row->used[TEXT_AREA];
17855 struct glyph *cursor = NULL;
17856
17857 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17858 int x = row->x;
17859 ptrdiff_t pt_old = PT - delta;
17860 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17861 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17862 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17863
17864
17865 struct glyph *glyphs_end = end;
17866
17867
17868 bool match_with_avoid_cursor = false;
17869
17870
17871 bool string_seen = false;
17872
17873
17874 ptrdiff_t bpos_max = pos_before;
17875 ptrdiff_t bpos_min = pos_after;
17876
17877
17878 ptrdiff_t bpos_covered = 0;
17879
17880
17881 bool string_from_text_prop = false;
17882
17883
17884
17885
17886 eassert (!row->mode_line_p);
17887 if (row->mode_line_p)
17888 return false;
17889
17890
17891
17892
17893 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17894 {
17895 if (!row->reversed_p)
17896 {
17897 while (glyph < end
17898 && NILP (glyph->object)
17899 && glyph->charpos < 0)
17900 {
17901 x += glyph->pixel_width;
17902 ++glyph;
17903 }
17904 while (end > glyph
17905 && NILP ((end - 1)->object)
17906
17907
17908 && (end - 1)->charpos <= 0)
17909 --end;
17910 glyph_before = glyph - 1;
17911 glyph_after = end;
17912 }
17913 else
17914 {
17915 struct glyph *g;
17916
17917
17918
17919 glyphs_end = end = glyph - 1;
17920 glyph += row->used[TEXT_AREA] - 1;
17921
17922 while (glyph > end + 1
17923 && NILP (glyph->object)
17924 && glyph->charpos < 0)
17925 --glyph;
17926 if (NILP (glyph->object) && glyph->charpos < 0)
17927 --glyph;
17928
17929
17930 for (x = 0, g = end + 1; g < glyph; g++)
17931 x += g->pixel_width;
17932 while (end < glyph
17933 && NILP ((end + 1)->object)
17934 && (end + 1)->charpos <= 0)
17935 ++end;
17936 glyph_before = glyph + 1;
17937 glyph_after = end;
17938 }
17939 }
17940 else if (row->reversed_p)
17941 {
17942
17943
17944
17945 cursor = end - 1;
17946
17947
17948
17949 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
17950 && !WINDOW_RIGHTMOST_P (w)
17951 && cursor == row->glyphs[LAST_AREA] - 1)
17952 cursor--;
17953 x = -1;
17954 }
17955
17956
17957
17958
17959
17960 if (!row->reversed_p)
17961 while (
17962 glyph < end
17963
17964 && !NILP (glyph->object))
17965 {
17966 if (BUFFERP (glyph->object))
17967 {
17968 ptrdiff_t dpos = glyph->charpos - pt_old;
17969
17970 if (glyph->charpos > bpos_max)
17971 bpos_max = glyph->charpos;
17972 if (glyph->charpos < bpos_min)
17973 bpos_min = glyph->charpos;
17974 if (!glyph->avoid_cursor_p)
17975 {
17976
17977
17978 if (dpos == 0)
17979 {
17980 match_with_avoid_cursor = false;
17981 break;
17982 }
17983
17984
17985 if (0 > dpos && dpos > pos_before - pt_old)
17986 {
17987 pos_before = glyph->charpos;
17988 glyph_before = glyph;
17989 }
17990 else if (0 < dpos && dpos < pos_after - pt_old)
17991 {
17992 pos_after = glyph->charpos;
17993 glyph_after = glyph;
17994 }
17995 }
17996 else if (dpos == 0)
17997 match_with_avoid_cursor = true;
17998 }
17999 else if (STRINGP (glyph->object))
18000 {
18001 Lisp_Object chprop;
18002 ptrdiff_t glyph_pos = glyph->charpos;
18003
18004 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18005 glyph->object);
18006 if (!NILP (chprop))
18007 {
18008
18009
18010
18011
18012
18013
18014
18015
18016
18017
18018 ptrdiff_t prop_pos =
18019 string_buffer_position_lim (glyph->object, pos_before,
18020 pos_after, false);
18021
18022 if (prop_pos >= pos_before)
18023 bpos_max = prop_pos;
18024 }
18025 if (FIXNUMP (chprop))
18026 {
18027 bpos_covered = bpos_max + XFIXNUM (chprop);
18028
18029
18030
18031
18032
18033
18034
18035
18036
18037
18038
18039 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18040 {
18041 cursor = glyph;
18042 break;
18043 }
18044 }
18045
18046 string_seen = true;
18047 }
18048 x += glyph->pixel_width;
18049 ++glyph;
18050 }
18051 else if (glyph > end)
18052 while (!NILP (glyph->object))
18053 {
18054 if (BUFFERP (glyph->object))
18055 {
18056 ptrdiff_t dpos = glyph->charpos - pt_old;
18057
18058 if (glyph->charpos > bpos_max)
18059 bpos_max = glyph->charpos;
18060 if (glyph->charpos < bpos_min)
18061 bpos_min = glyph->charpos;
18062 if (!glyph->avoid_cursor_p)
18063 {
18064 if (dpos == 0)
18065 {
18066 match_with_avoid_cursor = false;
18067 break;
18068 }
18069 if (0 > dpos && dpos > pos_before - pt_old)
18070 {
18071 pos_before = glyph->charpos;
18072 glyph_before = glyph;
18073 }
18074 else if (0 < dpos && dpos < pos_after - pt_old)
18075 {
18076 pos_after = glyph->charpos;
18077 glyph_after = glyph;
18078 }
18079 }
18080 else if (dpos == 0)
18081 match_with_avoid_cursor = true;
18082 }
18083 else if (STRINGP (glyph->object))
18084 {
18085 Lisp_Object chprop;
18086 ptrdiff_t glyph_pos = glyph->charpos;
18087
18088 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18089 glyph->object);
18090 if (!NILP (chprop))
18091 {
18092 ptrdiff_t prop_pos =
18093 string_buffer_position_lim (glyph->object, pos_before,
18094 pos_after, false);
18095
18096 if (prop_pos >= pos_before)
18097 bpos_max = prop_pos;
18098 }
18099 if (FIXNUMP (chprop))
18100 {
18101 bpos_covered = bpos_max + XFIXNUM (chprop);
18102
18103
18104
18105 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18106 {
18107 cursor = glyph;
18108 break;
18109 }
18110 }
18111 string_seen = true;
18112 }
18113 --glyph;
18114 if (glyph == glyphs_end)
18115 {
18116 x--;
18117 break;
18118 }
18119 x -= glyph->pixel_width;
18120 }
18121
18122
18123
18124
18125 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18126 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
18127 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
18128 {
18129
18130
18131
18132
18133
18134 bool empty_line_p =
18135 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18136 && NILP (glyph->object) && glyph->charpos > 0
18137
18138
18139
18140
18141 && !(row->continued_p || row->truncated_on_right_p));
18142
18143 if (row->ends_in_ellipsis_p && pos_after == last_pos)
18144 {
18145 ptrdiff_t ellipsis_pos;
18146
18147
18148 if (!row->reversed_p)
18149 {
18150 ellipsis_pos = (glyph - 1)->charpos;
18151 while (glyph > row->glyphs[TEXT_AREA]
18152 && (glyph - 1)->charpos == ellipsis_pos)
18153 glyph--, x -= glyph->pixel_width;
18154
18155
18156
18157 x += glyph->pixel_width;
18158 glyph++;
18159 }
18160 else
18161 {
18162 ellipsis_pos = (glyph + 1)->charpos;
18163 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18164 && (glyph + 1)->charpos == ellipsis_pos)
18165 glyph++, x += glyph->pixel_width;
18166 x -= glyph->pixel_width;
18167 glyph--;
18168 }
18169 }
18170 else if (match_with_avoid_cursor)
18171 {
18172 cursor = glyph_after;
18173 x = -1;
18174 }
18175 else if (string_seen)
18176 {
18177 int incr = row->reversed_p ? -1 : +1;
18178
18179
18180
18181
18182
18183
18184 struct glyph *start, *stop;
18185 ptrdiff_t pos = pos_before;
18186
18187 x = -1;
18188
18189
18190
18191
18192
18193
18194 if (row->ends_in_newline_from_string_p)
18195 {
18196 glyph_after = end;
18197 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18198 }
18199
18200
18201
18202
18203
18204
18205
18206
18207
18208 if (!row->reversed_p)
18209 {
18210 start = min (glyph_before, glyph_after);
18211 stop = max (glyph_before, glyph_after);
18212 }
18213 else
18214 {
18215 start = max (glyph_before, glyph_after);
18216 stop = min (glyph_before, glyph_after);
18217 }
18218 for (glyph = start + incr;
18219 row->reversed_p ? glyph > stop : glyph < stop; )
18220 {
18221
18222
18223
18224
18225 if (STRINGP (glyph->object))
18226 {
18227 Lisp_Object str;
18228 ptrdiff_t tem;
18229
18230
18231 ptrdiff_t lim = pos_after
18232 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18233
18234 string_from_text_prop = false;
18235 str = glyph->object;
18236 tem = string_buffer_position_lim (str, pos, lim, false);
18237 if (tem == 0
18238 || pos <= tem)
18239 {
18240
18241
18242
18243
18244
18245
18246
18247
18248
18249
18250 if (tem == 0
18251 || tem == pt_old
18252 || (tem - pt_old > 0 && tem < pos_after))
18253 {
18254
18255
18256
18257
18258
18259
18260 ptrdiff_t strpos = glyph->charpos;
18261
18262 if (tem)
18263 {
18264 cursor = glyph;
18265 string_from_text_prop = true;
18266 }
18267 for ( ;
18268 (row->reversed_p ? glyph > stop : glyph < stop)
18269 && EQ (glyph->object, str);
18270 glyph += incr)
18271 {
18272 Lisp_Object cprop;
18273 ptrdiff_t gpos = glyph->charpos;
18274
18275 cprop = Fget_char_property (make_fixnum (gpos),
18276 Qcursor,
18277 glyph->object);
18278 if (!NILP (cprop))
18279 {
18280 cursor = glyph;
18281 break;
18282 }
18283 if (tem && glyph->charpos < strpos)
18284 {
18285 strpos = glyph->charpos;
18286 cursor = glyph;
18287 }
18288 }
18289
18290 if (tem == pt_old
18291 || (tem - pt_old > 0 && tem < pos_after))
18292 goto compute_x;
18293 }
18294 if (tem)
18295 pos = tem + 1;
18296 }
18297
18298
18299 while ((row->reversed_p ? glyph > stop : glyph < stop)
18300 && EQ (glyph->object, str))
18301 glyph += incr;
18302 }
18303 else
18304 glyph += incr;
18305 }
18306
18307
18308
18309 if (cursor == NULL
18310 && (row->reversed_p ? glyph <= end : glyph >= end)
18311 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18312 && STRINGP (end->object)
18313 && row->continued_p)
18314 return false;
18315 }
18316
18317
18318
18319
18320
18321 else if (row->truncated_on_left_p && pt_old < bpos_min)
18322 {
18323 cursor = glyph_before;
18324 x = -1;
18325 }
18326 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18327
18328 || (!empty_line_p
18329 && (row->reversed_p
18330 ? glyph_after > glyphs_end
18331 : glyph_after < glyphs_end)))
18332 {
18333 cursor = glyph_after;
18334 x = -1;
18335 }
18336 }
18337
18338 compute_x:
18339 if (cursor != NULL)
18340 glyph = cursor;
18341 else if (glyph == glyphs_end
18342 && pos_before == pos_after
18343 && STRINGP ((row->reversed_p
18344 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18345 : row->glyphs[TEXT_AREA])->object))
18346 {
18347
18348
18349
18350
18351 glyph =
18352 row->reversed_p
18353 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18354 : row->glyphs[TEXT_AREA];
18355 }
18356 if (x < 0)
18357 {
18358 struct glyph *g;
18359
18360
18361 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18362 {
18363 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18364 emacs_abort ();
18365 x += g->pixel_width;
18366 }
18367 }
18368
18369
18370
18371
18372
18373
18374 if (
18375 w->cursor.vpos >= 0
18376
18377 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18378
18379
18380
18381
18382
18383 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18384 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18385 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18386 {
18387 struct glyph *g1
18388 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18389
18390
18391 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18392 return false;
18393
18394
18395 if (
18396 w->cursor.hpos >= 0
18397 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18398 && ((BUFFERP (g1->object)
18399 && (g1->charpos == pt_old
18400 || (BUFFERP (glyph->object)
18401 && eabs (g1->charpos - pt_old)
18402 < eabs (glyph->charpos - pt_old))))
18403
18404
18405 || (STRINGP (g1->object)
18406 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18407 Qcursor, g1->object))
18408
18409
18410
18411 || (EQ (g1->object, glyph->object)
18412 && string_from_text_prop)
18413
18414
18415 || (NILP (glyph->object)
18416 && glyph->charpos != pt_old)))))
18417 return false;
18418
18419 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18420
18421
18422
18423 || (!row->continued_p
18424 && NILP (glyph->object)
18425 && glyph->charpos == 0
18426 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18427
18428
18429
18430
18431
18432 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18433 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18434 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18435 return false;
18436 }
18437 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18438 w->cursor.x = x;
18439 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18440 w->cursor.y = row->y + dy;
18441
18442 if (w == XWINDOW (selected_window))
18443 {
18444 if (!row->continued_p
18445 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18446 && row->x == 0)
18447 {
18448 this_line_buffer = XBUFFER (w->contents);
18449
18450 CHARPOS (this_line_start_pos)
18451 = MATRIX_ROW_START_CHARPOS (row) + delta;
18452 BYTEPOS (this_line_start_pos)
18453 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18454
18455 CHARPOS (this_line_end_pos)
18456 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18457 BYTEPOS (this_line_end_pos)
18458 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18459
18460 this_line_y = w->cursor.y;
18461 this_line_pixel_height = row->height;
18462 this_line_vpos = w->cursor.vpos;
18463 this_line_start_x = row->x;
18464 }
18465 else
18466 CHARPOS (this_line_start_pos) = 0;
18467 }
18468
18469 return true;
18470 }
18471
18472
18473
18474
18475
18476
18477
18478 static struct text_pos
18479 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18480 {
18481 struct window *w = XWINDOW (window);
18482 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18483
18484 eassert (current_buffer == XBUFFER (w->contents));
18485
18486 if (!NILP (Vwindow_scroll_functions))
18487 {
18488 specpdl_ref count = SPECPDL_INDEX ();
18489 specbind (Qinhibit_quit, Qt);
18490 safe_run_hooks_2
18491 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18492 unbind_to (count, Qnil);
18493 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18494
18495 set_buffer_internal (XBUFFER (w->contents));
18496 }
18497
18498 return startp;
18499 }
18500
18501
18502
18503
18504
18505
18506
18507
18508
18509
18510
18511
18512
18513
18514
18515
18516
18517
18518
18519
18520
18521
18522 static bool
18523 cursor_row_fully_visible_p (struct window *w, bool force_p,
18524 bool current_matrix_p,
18525 bool just_test_user_preference_p)
18526 {
18527 struct glyph_matrix *matrix;
18528 struct glyph_row *row;
18529 int window_height;
18530 Lisp_Object mclfv_p =
18531 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18532
18533
18534 if (BASE_EQ (mclfv_p, Qunbound))
18535 mclfv_p = Vmake_cursor_line_fully_visible;
18536
18537
18538 if (FUNCTIONP (mclfv_p))
18539 {
18540 Lisp_Object window;
18541 XSETWINDOW (window, w);
18542
18543
18544 Lisp_Object val = safe_call1 (mclfv_p, window);
18545 if (NILP (val))
18546 return true;
18547 else if (just_test_user_preference_p)
18548 return false;
18549 }
18550 else if (NILP (mclfv_p))
18551 return true;
18552 else if (just_test_user_preference_p)
18553 return false;
18554
18555
18556
18557 if (w->cursor.vpos < 0)
18558 return true;
18559
18560 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18561 row = MATRIX_ROW (matrix, w->cursor.vpos);
18562
18563
18564 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18565 return true;
18566
18567
18568
18569 window_height = window_box_height (w);
18570 if (row->height >= window_height)
18571 {
18572 if (!force_p || MINI_WINDOW_P (w)
18573 || w->vscroll || w->cursor.vpos == 0)
18574 return true;
18575 }
18576 return false;
18577 }
18578
18579
18580
18581
18582
18583
18584
18585
18586
18587
18588
18589
18590
18591
18592
18593
18594
18595
18596
18597
18598 enum
18599 {
18600 SCROLLING_SUCCESS = 1,
18601 SCROLLING_FAILED = 0,
18602 SCROLLING_NEED_LARGER_MATRICES = -1
18603 };
18604
18605
18606
18607
18608
18609 #define SCROLL_LIMIT 100
18610
18611 static int
18612 try_scrolling (Lisp_Object window, bool just_this_one_p,
18613 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18614 bool temp_scroll_step, bool last_line_misfit)
18615 {
18616 struct window *w = XWINDOW (window);
18617 struct text_pos pos, startp;
18618 struct it it;
18619 int this_scroll_margin, scroll_max, rc, height;
18620 int dy = 0, amount_to_scroll = 0;
18621 bool scroll_down_p = false;
18622 int extra_scroll_margin_lines = last_line_misfit;
18623 Lisp_Object aggressive;
18624
18625 int scroll_limit = SCROLL_LIMIT;
18626 int frame_line_height = default_line_pixel_height (w);
18627
18628 #ifdef GLYPH_DEBUG
18629 debug_method_add (w, "try_scrolling");
18630 #endif
18631
18632 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18633
18634 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18635
18636
18637
18638
18639
18640 if (arg_scroll_conservatively > scroll_limit)
18641 {
18642 arg_scroll_conservatively = scroll_limit + 1;
18643 scroll_max = scroll_limit * frame_line_height;
18644 }
18645 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18646
18647
18648 {
18649 intmax_t scroll_lines_max
18650 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18651 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18652 scroll_max = scroll_lines * frame_line_height;
18653 }
18654 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18655 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18656
18657
18658 scroll_max = 10 * frame_line_height;
18659 else
18660 scroll_max = 0;
18661
18662 too_near_end:
18663
18664
18665 if (PT > CHARPOS (startp))
18666 {
18667 int scroll_margin_y;
18668
18669
18670
18671 start_display (&it, w, startp);
18672 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18673 - this_scroll_margin
18674 - frame_line_height * extra_scroll_margin_lines;
18675 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18676 (MOVE_TO_POS | MOVE_TO_Y));
18677
18678 if (PT > CHARPOS (it.current.pos))
18679 {
18680 int y0 = line_bottom_y (&it);
18681
18682
18683
18684
18685
18686 int slack = max (scroll_max, 10 * frame_line_height);
18687 int y_to_move = it.last_visible_y + slack;
18688
18689
18690
18691
18692
18693 move_it_to (&it, PT, -1, y_to_move,
18694 -1, MOVE_TO_POS | MOVE_TO_Y);
18695 dy = line_bottom_y (&it) - y0;
18696
18697 if (dy > scroll_max)
18698 return SCROLLING_FAILED;
18699
18700 if (dy > 0)
18701 scroll_down_p = true;
18702 }
18703 else if (PT == IT_CHARPOS (it)
18704 && IT_CHARPOS (it) < ZV
18705 && it.method == GET_FROM_STRING
18706 && arg_scroll_conservatively > scroll_limit
18707 && it.current_x == 0)
18708 {
18709 enum move_it_result skip;
18710 int y1 = it.current_y;
18711 int vpos;
18712
18713
18714
18715
18716
18717
18718
18719 do {
18720 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18721 if (skip != MOVE_NEWLINE_OR_CR
18722 || IT_CHARPOS (it) != PT
18723 || it.method == GET_FROM_BUFFER)
18724 break;
18725 vpos = it.vpos;
18726 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18727 } while (it.vpos > vpos);
18728
18729 dy = it.current_y - y1;
18730
18731 if (dy > scroll_max)
18732 return SCROLLING_FAILED;
18733
18734 if (dy > 0)
18735 scroll_down_p = true;
18736 }
18737 }
18738
18739 if (scroll_down_p)
18740 {
18741
18742
18743
18744
18745 if (arg_scroll_conservatively)
18746 amount_to_scroll
18747 = min (max (dy, frame_line_height),
18748 frame_line_height * arg_scroll_conservatively);
18749 else if (scroll_step || temp_scroll_step)
18750 amount_to_scroll = scroll_max;
18751 else
18752 {
18753 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18754 height = WINDOW_BOX_TEXT_HEIGHT (w);
18755 if (NUMBERP (aggressive))
18756 {
18757 double float_amount = XFLOATINT (aggressive) * height;
18758 int aggressive_scroll = float_amount;
18759 if (aggressive_scroll == 0 && float_amount > 0)
18760 aggressive_scroll = 1;
18761
18762
18763
18764
18765
18766
18767 if (aggressive_scroll + 2 * this_scroll_margin > height)
18768 aggressive_scroll = height - 2 * this_scroll_margin;
18769 amount_to_scroll = dy + aggressive_scroll;
18770 }
18771 }
18772
18773 if (amount_to_scroll <= 0)
18774 return SCROLLING_FAILED;
18775
18776 start_display (&it, w, startp);
18777 if (arg_scroll_conservatively <= scroll_limit)
18778 move_it_vertically (&it, amount_to_scroll);
18779 else
18780 {
18781
18782
18783
18784
18785
18786
18787 struct it it1;
18788 void *it1data = NULL;
18789
18790
18791 int start_y;
18792
18793 SAVE_IT (it1, it, it1data);
18794 start_y = line_bottom_y (&it1);
18795 do {
18796 RESTORE_IT (&it, &it, it1data);
18797 move_it_by_lines (&it, 1);
18798 SAVE_IT (it1, it, it1data);
18799 } while (IT_CHARPOS (it) < ZV
18800 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18801 bidi_unshelve_cache (it1data, true);
18802 }
18803
18804
18805 if (IT_CHARPOS (it) == CHARPOS (startp))
18806 move_it_by_lines (&it, 1);
18807 startp = it.current.pos;
18808 }
18809 else
18810 {
18811 struct text_pos scroll_margin_pos = startp;
18812 int y_offset = 0;
18813
18814
18815
18816 if (this_scroll_margin)
18817 {
18818 int y_start;
18819
18820 start_display (&it, w, startp);
18821 y_start = it.current_y;
18822 move_it_vertically (&it, this_scroll_margin);
18823 scroll_margin_pos = it.current.pos;
18824
18825
18826
18827 if (IT_CHARPOS (it) == ZV
18828 && it.current_y - y_start < this_scroll_margin)
18829 y_offset = this_scroll_margin - (it.current_y - y_start);
18830 }
18831
18832 if (PT < CHARPOS (scroll_margin_pos))
18833 {
18834
18835
18836 int y0, y_to_move;
18837
18838
18839
18840
18841
18842
18843 SET_TEXT_POS (pos, PT, PT_BYTE);
18844 start_display (&it, w, pos);
18845 y0 = it.current_y;
18846 y_to_move = max (it.last_visible_y,
18847 max (scroll_max, 10 * frame_line_height));
18848 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18849 y_to_move, -1,
18850 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18851 dy = it.current_y - y0;
18852 if (dy > scroll_max
18853 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18854 return SCROLLING_FAILED;
18855
18856
18857 dy += y_offset;
18858
18859
18860 start_display (&it, w, startp);
18861
18862 if (arg_scroll_conservatively)
18863 amount_to_scroll
18864 = min (max (dy, frame_line_height),
18865 frame_line_height * arg_scroll_conservatively);
18866 else if (scroll_step || temp_scroll_step)
18867 amount_to_scroll = scroll_max;
18868 else
18869 {
18870 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18871 height = WINDOW_BOX_TEXT_HEIGHT (w);
18872 if (NUMBERP (aggressive))
18873 {
18874 double float_amount = XFLOATINT (aggressive) * height;
18875 int aggressive_scroll = float_amount;
18876 if (aggressive_scroll == 0 && float_amount > 0)
18877 aggressive_scroll = 1;
18878
18879
18880
18881
18882 if (aggressive_scroll + 2 * this_scroll_margin > height)
18883 aggressive_scroll = height - 2 * this_scroll_margin;
18884 amount_to_scroll = dy + aggressive_scroll;
18885 }
18886 }
18887
18888 if (amount_to_scroll <= 0)
18889 return SCROLLING_FAILED;
18890
18891 move_it_vertically_backward (&it, amount_to_scroll);
18892 startp = it.current.pos;
18893 }
18894 }
18895
18896
18897 startp = run_window_scroll_functions (window, startp);
18898
18899
18900
18901 if (!try_window (window, startp, 0))
18902 rc = SCROLLING_NEED_LARGER_MATRICES;
18903 else if (w->cursor.vpos < 0)
18904 {
18905 clear_glyph_matrix (w->desired_matrix);
18906 rc = SCROLLING_FAILED;
18907 }
18908 else
18909 {
18910
18911 if (!just_this_one_p
18912 || current_buffer->clip_changed
18913 || BEG_UNCHANGED < CHARPOS (startp))
18914 w->base_line_number = 0;
18915
18916
18917
18918 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18919 false, false)
18920
18921
18922
18923 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18924 {
18925 clear_glyph_matrix (w->desired_matrix);
18926 ++extra_scroll_margin_lines;
18927 goto too_near_end;
18928 }
18929 rc = SCROLLING_SUCCESS;
18930 }
18931
18932 return rc;
18933 }
18934
18935
18936
18937
18938
18939
18940
18941
18942
18943
18944
18945
18946 static bool
18947 compute_window_start_on_continuation_line (struct window *w)
18948 {
18949 struct text_pos pos, start_pos, pos_before_pt;
18950 bool window_start_changed_p = false;
18951
18952 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
18953
18954
18955
18956
18957 if (CHARPOS (start_pos) > BEGV
18958 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
18959 {
18960 struct it it;
18961 struct glyph_row *row;
18962
18963
18964 if (CHARPOS (start_pos) < BEGV)
18965 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
18966 else if (CHARPOS (start_pos) > ZV)
18967 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
18968
18969
18970
18971 row = w->desired_matrix->rows + window_wants_tab_line (w)
18972 + window_wants_header_line (w);
18973 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
18974 row, DEFAULT_FACE_ID);
18975 reseat_at_previous_visible_line_start (&it);
18976
18977
18978
18979
18980
18981
18982
18983 if (IT_CHARPOS (it) <= PT
18984 && (CHARPOS (start_pos) - IT_CHARPOS (it)
18985
18986 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
18987 {
18988 int min_distance, distance;
18989
18990
18991
18992
18993
18994
18995
18996 pos_before_pt = pos = it.current.pos;
18997 min_distance = DISP_INFINITY;
18998 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
18999 distance < min_distance)
19000 {
19001 min_distance = distance;
19002 if (CHARPOS (pos) <= PT)
19003 pos_before_pt = pos;
19004 pos = it.current.pos;
19005 if (it.line_wrap == WORD_WRAP)
19006 {
19007
19008
19009
19010
19011
19012
19013
19014
19015
19016 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
19017 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19018 move_it_to (&it, ZV, 0,
19019 it.current_y + it.max_ascent + it.max_descent, -1,
19020 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19021 }
19022 else
19023 move_it_by_lines (&it, 1);
19024 }
19025
19026
19027
19028
19029
19030 if (CHARPOS (pos) > PT)
19031 pos = pos_before_pt;
19032
19033
19034 SET_MARKER_FROM_TEXT_POS (w->start, pos);
19035 window_start_changed_p = true;
19036 }
19037 }
19038
19039 return window_start_changed_p;
19040 }
19041
19042
19043
19044
19045
19046
19047
19048
19049
19050
19051
19052
19053
19054
19055
19056
19057
19058 enum
19059 {
19060 CURSOR_MOVEMENT_SUCCESS,
19061 CURSOR_MOVEMENT_CANNOT_BE_USED,
19062 CURSOR_MOVEMENT_MUST_SCROLL,
19063 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
19064 };
19065
19066 static int
19067 try_cursor_movement (Lisp_Object window, struct text_pos startp,
19068 bool *scroll_step)
19069 {
19070 struct window *w = XWINDOW (window);
19071 struct frame *f = XFRAME (w->frame);
19072 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
19073
19074 #ifdef GLYPH_DEBUG
19075 if (inhibit_try_cursor_movement)
19076 return rc;
19077 #endif
19078
19079
19080
19081
19082 eassert (w->last_point > 0);
19083
19084
19085
19086 eassert (!w->window_end_valid
19087 || w->window_end_vpos < w->current_matrix->nrows);
19088
19089
19090
19091 if (
19092 PT >= CHARPOS (startp)
19093
19094 && !current_buffer->clip_changed
19095
19096
19097
19098
19099 && !update_mode_lines
19100 && !windows_or_buffers_changed
19101 && !f->cursor_type_changed
19102 && NILP (Vshow_trailing_whitespace)
19103
19104
19105 && !EQ (Vdisplay_line_numbers, Qrelative)
19106 && !EQ (Vdisplay_line_numbers, Qvisual)
19107
19108
19109
19110 && !(!NILP (Vdisplay_line_numbers)
19111 && NILP (Finternal_lisp_face_equal_p (Qline_number,
19112 Qline_number_current_line,
19113 w->frame)))
19114
19115
19116
19117
19118
19119
19120 && !EQ (window, minibuf_window)
19121
19122
19123
19124 && !overlay_arrow_in_current_buffer_p ())
19125 {
19126 int this_scroll_margin, top_scroll_margin;
19127 struct glyph_row *row = NULL;
19128
19129 #ifdef GLYPH_DEBUG
19130 debug_method_add (w, "cursor movement");
19131 #endif
19132
19133 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
19134
19135 top_scroll_margin = this_scroll_margin;
19136 if (window_wants_tab_line (w))
19137 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
19138 if (window_wants_header_line (w))
19139 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
19140
19141
19142
19143 if (w->last_cursor_vpos < 0
19144 || w->last_cursor_vpos >= w->current_matrix->nrows)
19145 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19146 else
19147 {
19148 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
19149
19150 if (row->tab_line_p)
19151 ++row;
19152 if (row->mode_line_p)
19153 ++row;
19154 if (!row->enabled_p)
19155 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19156 }
19157
19158 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
19159 {
19160 bool scroll_p = false, must_scroll = false;
19161 int last_y = window_text_bottom_y (w) - this_scroll_margin;
19162
19163 if (PT > w->last_point)
19164 {
19165
19166 while (MATRIX_ROW_END_CHARPOS (row) < PT
19167 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19168 {
19169 eassert (row->enabled_p);
19170 ++row;
19171 }
19172
19173
19174
19175
19176 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19177 && MATRIX_ROW_END_CHARPOS (row) == PT
19178 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
19179 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19180 && !cursor_row_p (row))
19181 ++row;
19182
19183
19184
19185
19186
19187 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19188 || PT > MATRIX_ROW_END_CHARPOS (row)
19189
19190
19191 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19192 && PT == MATRIX_ROW_END_CHARPOS (row)
19193 && !row->ends_at_zv_p
19194 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19195 scroll_p = true;
19196 }
19197 else if (PT < w->last_point)
19198 {
19199
19200
19201 struct glyph_row *row0 = row;
19202
19203 while (!row->mode_line_p
19204 && (MATRIX_ROW_START_CHARPOS (row) > PT
19205 || (MATRIX_ROW_START_CHARPOS (row) == PT
19206 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19207 || (
19208 row > w->current_matrix->rows
19209 && (row-1)->ends_in_newline_from_string_p))))
19210 && (row->y > top_scroll_margin
19211 || CHARPOS (startp) == BEGV))
19212 {
19213 eassert (row->enabled_p);
19214 --row;
19215 }
19216
19217
19218
19219
19220
19221 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19222 && PT <= MATRIX_ROW_END_CHARPOS (row))
19223 && row0->continued_p)
19224 {
19225 row = row0;
19226 while (MATRIX_ROW_START_CHARPOS (row) > PT
19227 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19228 {
19229 eassert (row->enabled_p);
19230 ++row;
19231 }
19232 }
19233
19234
19235
19236
19237
19238
19239 if (row < w->current_matrix->rows
19240 || row->mode_line_p)
19241 {
19242 row = w->current_matrix->rows;
19243
19244 if (row->tab_line_p)
19245 ++row;
19246 if (row->mode_line_p)
19247 ++row;
19248 }
19249
19250
19251
19252 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19253 && MATRIX_ROW_END_CHARPOS (row) == PT
19254 && !cursor_row_p (row))
19255 ++row;
19256
19257
19258
19259 if ((row->y < top_scroll_margin
19260 && CHARPOS (startp) != BEGV)
19261 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19262 || PT > MATRIX_ROW_END_CHARPOS (row)
19263 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19264 && PT == MATRIX_ROW_END_CHARPOS (row)
19265 && !row->ends_at_zv_p
19266 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19267 scroll_p = true;
19268 }
19269 else
19270 {
19271
19272
19273 rc = CURSOR_MOVEMENT_SUCCESS;
19274 }
19275
19276 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19277 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19278
19279
19280 || (MATRIX_ROW_END_CHARPOS (row-1)
19281 == MATRIX_ROW_START_CHARPOS (row))))
19282 || PT > MATRIX_ROW_END_CHARPOS (row))
19283 {
19284
19285 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19286 must_scroll = true;
19287 }
19288 else if (rc != CURSOR_MOVEMENT_SUCCESS
19289 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19290 {
19291 struct glyph_row *row1;
19292
19293
19294
19295
19296
19297
19298
19299
19300
19301
19302
19303 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19304 MATRIX_ROW_CONTINUATION_LINE_P (row);
19305 --row)
19306 {
19307
19308
19309
19310 if (row <= row1)
19311 {
19312 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19313 break;
19314 }
19315 eassert (row->enabled_p);
19316 }
19317 }
19318 if (must_scroll)
19319 ;
19320 else if (rc != CURSOR_MOVEMENT_SUCCESS
19321 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19322
19323
19324
19325 && !row->mode_line_p
19326 && !cursor_row_fully_visible_p (w, true, true, true))
19327 {
19328 if (PT == MATRIX_ROW_END_CHARPOS (row)
19329 && !row->ends_at_zv_p
19330 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19331 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19332 else if (row->height > window_box_height (w))
19333 {
19334
19335
19336
19337
19338 *scroll_step = true;
19339 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19340 }
19341 else
19342 {
19343 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19344 if (!cursor_row_fully_visible_p (w, false, true, false))
19345 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19346 else
19347 rc = CURSOR_MOVEMENT_SUCCESS;
19348 }
19349 }
19350 else if (scroll_p)
19351 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19352 else if (rc != CURSOR_MOVEMENT_SUCCESS
19353 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19354 {
19355
19356
19357
19358
19359
19360
19361
19362 bool rv = false;
19363 bool pt_invis = false;
19364 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19365 Qinvisible,
19366 Qnil, NULL);
19367
19368 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19369 pt_invis = true;
19370
19371 do
19372 {
19373 bool at_zv_p = false, exact_match_p = false;
19374
19375
19376
19377
19378
19379 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19380 && PT <= MATRIX_ROW_END_CHARPOS (row)
19381 && cursor_row_p (row))
19382 rv |= set_cursor_from_row (w, row, w->current_matrix,
19383 0, 0, 0, 0);
19384
19385
19386
19387 if (rv)
19388 {
19389 at_zv_p = MATRIX_ROW (w->current_matrix,
19390 w->cursor.vpos)->ends_at_zv_p;
19391 if (!at_zv_p
19392 && w->cursor.hpos >= 0
19393 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19394 w->cursor.vpos))
19395 {
19396 struct glyph_row *candidate =
19397 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19398 struct glyph *g =
19399 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19400 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19401
19402 exact_match_p =
19403 (BUFFERP (g->object) && g->charpos == PT)
19404 || (NILP (g->object)
19405 && (g->charpos == PT
19406 || (g->charpos == 0 && endpos - 1 == PT)));
19407
19408
19409
19410
19411 if (!exact_match_p && pt_invis)
19412 exact_match_p = true;
19413 }
19414 if (at_zv_p || exact_match_p)
19415 {
19416 rc = CURSOR_MOVEMENT_SUCCESS;
19417 break;
19418 }
19419 }
19420 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19421 break;
19422 ++row;
19423 }
19424 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19425 || row->continued_p)
19426 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19427 || (MATRIX_ROW_START_CHARPOS (row) == PT
19428 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19429
19430
19431
19432 if (rc != CURSOR_MOVEMENT_SUCCESS
19433 && !(rv
19434 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19435 && !row->continued_p))
19436 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19437 else if (rv)
19438 rc = CURSOR_MOVEMENT_SUCCESS;
19439 }
19440 else
19441 {
19442 do
19443 {
19444 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19445 {
19446 rc = CURSOR_MOVEMENT_SUCCESS;
19447 break;
19448 }
19449 ++row;
19450 }
19451 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19452 && MATRIX_ROW_START_CHARPOS (row) == PT
19453 && cursor_row_p (row));
19454 }
19455 }
19456 }
19457
19458 return rc;
19459 }
19460
19461
19462 void
19463 set_vertical_scroll_bar (struct window *w)
19464 {
19465 ptrdiff_t start, end, whole;
19466
19467
19468
19469
19470
19471
19472
19473
19474 if (!MINI_WINDOW_P (w)
19475 || (w == XWINDOW (minibuf_window)
19476 && NILP (echo_area_buffer[0])))
19477 {
19478 struct buffer *buf = XBUFFER (w->contents);
19479
19480 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19481 start = marker_position (w->start) - BUF_BEGV (buf);
19482 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19483
19484
19485
19486
19487 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19488 {
19489 struct it it;
19490 struct text_pos start_pos;
19491 struct buffer *obuf = current_buffer;
19492
19493
19494
19495 set_buffer_internal_1 (XBUFFER (w->contents));
19496 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19497 start_display (&it, w, start_pos);
19498 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19499 MOVE_TO_X | MOVE_TO_Y);
19500 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19501 set_buffer_internal_1 (obuf);
19502 }
19503
19504 if (end < start)
19505 end = start;
19506 if (whole < (end - start))
19507 whole = end - start;
19508 }
19509 else
19510 start = end = whole = 0;
19511
19512
19513 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19514 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19515 (w, end - start, whole, start);
19516 }
19517
19518
19519 void
19520 set_horizontal_scroll_bar (struct window *w)
19521 {
19522 int start, end, whole, portion;
19523
19524 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19525 {
19526 struct buffer *b = XBUFFER (w->contents);
19527 struct buffer *old_buffer = NULL;
19528 struct it it;
19529 struct text_pos startp;
19530
19531 if (b != current_buffer)
19532 {
19533 old_buffer = current_buffer;
19534 set_buffer_internal (b);
19535 }
19536
19537 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19538 start_display (&it, w, startp);
19539 it.last_visible_x = INT_MAX;
19540 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19541 MOVE_TO_X | MOVE_TO_Y);
19542
19543
19544
19545
19546 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19547 end = start + window_box_width (w, TEXT_AREA);
19548 portion = end - start;
19549
19550
19551
19552
19553 whole = max (whole, end);
19554
19555 if (it.bidi_p)
19556 {
19557 Lisp_Object pdir;
19558
19559 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19560 if (EQ (pdir, Qright_to_left))
19561 {
19562 start = whole - end;
19563 end = start + portion;
19564 }
19565 }
19566
19567 if (old_buffer)
19568 set_buffer_internal (old_buffer);
19569 }
19570 else
19571 start = end = whole = portion = 0;
19572
19573 w->hscroll_whole = whole;
19574
19575
19576 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19577 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19578 (w, portion, whole, start);
19579 }
19580
19581
19582
19583 static bool
19584 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19585 {
19586 if (!make_window_start_visible)
19587 return true;
19588
19589 struct window *w = XWINDOW (window);
19590 struct frame *f = XFRAME (w->frame);
19591 Lisp_Object startpos = make_fixnum (startp);
19592 Lisp_Object invprop, disp_spec;
19593 struct text_pos ignored;
19594
19595
19596 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19597 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19598 return false;
19599
19600
19601 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19602 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19603 FRAME_WINDOW_P (f)) > 0)
19604 return false;
19605
19606 return true;
19607 }
19608
19609 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19610 0, 0, 0,
19611 doc:
19612
19613 )
19614 (void)
19615 {
19616 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19617 }
19618
19619
19620
19621
19622
19623
19624
19625
19626
19627
19628
19629
19630
19631
19632
19633
19634
19635
19636
19637
19638
19639
19640
19641
19642
19643
19644
19645
19646
19647
19648
19649
19650
19651
19652
19653
19654
19655
19656
19657
19658
19659
19660
19661
19662
19663
19664
19665
19666
19667
19668
19669 static void
19670 redisplay_window (Lisp_Object window, bool just_this_one_p)
19671 {
19672 struct window *w = XWINDOW (window);
19673 struct frame *f = XFRAME (w->frame);
19674 struct buffer *buffer = XBUFFER (w->contents);
19675 struct buffer *old = current_buffer;
19676 struct text_pos lpoint, opoint, startp;
19677 bool update_mode_line;
19678 int tem;
19679 struct it it;
19680
19681 bool current_matrix_up_to_date_p = false;
19682 bool used_current_matrix_p = false;
19683
19684
19685 bool buffer_unchanged_p = false;
19686 bool temp_scroll_step = false;
19687 specpdl_ref count = SPECPDL_INDEX ();
19688 int rc;
19689 int centering_position = -1;
19690 bool last_line_misfit = false;
19691 ptrdiff_t beg_unchanged, end_unchanged;
19692 int frame_line_height, margin;
19693 bool use_desired_matrix;
19694 void *itdata = NULL;
19695
19696 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19697 opoint = lpoint;
19698
19699 #ifdef GLYPH_DEBUG
19700 *w->desired_matrix->method = 0;
19701 #endif
19702
19703 if (!just_this_one_p && needs_no_redisplay (w))
19704 return;
19705
19706
19707 eassert (XMARKER (w->start)->buffer == buffer);
19708 eassert (XMARKER (w->pointm)->buffer == buffer);
19709
19710 reconsider_clip_changes (w);
19711 frame_line_height = default_line_pixel_height (w);
19712 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19713
19714
19715
19716 update_mode_line = (w->update_mode_line
19717 || update_mode_lines
19718 || buffer->clip_changed
19719 || buffer->prevent_redisplay_optimizations_p);
19720
19721 if (!just_this_one_p)
19722
19723
19724 w->must_be_updated_p = true;
19725
19726 if (MINI_WINDOW_P (w))
19727 {
19728 if (w == XWINDOW (echo_area_window)
19729 && !NILP (echo_area_buffer[0]))
19730 {
19731 if (update_mode_line)
19732
19733
19734 goto finish_menu_bars;
19735 else
19736
19737 goto finish_scroll_bars;
19738 }
19739 else if ((w != XWINDOW (minibuf_window)
19740 || minibuf_level == 0)
19741
19742 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19743
19744
19745 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19746 {
19747
19748
19749 int yb = window_text_bottom_y (w);
19750 struct glyph_row *row;
19751 int y;
19752
19753 for (y = 0, row = w->desired_matrix->rows;
19754 y < yb;
19755 y += row->height, ++row)
19756 blank_row (w, row, y);
19757 goto finish_scroll_bars;
19758 }
19759 else if (minibuf_level >= 1)
19760 {
19761
19762
19763
19764 resize_mini_window (w, false);
19765 }
19766
19767 clear_glyph_matrix (w->desired_matrix);
19768 }
19769
19770
19771
19772
19773
19774 set_buffer_internal_1 (XBUFFER (w->contents));
19775
19776 current_matrix_up_to_date_p
19777 = (w->window_end_valid
19778 && !current_buffer->clip_changed
19779 && !current_buffer->prevent_redisplay_optimizations_p
19780 && !window_outdated (w)
19781 && !composition_break_at_point
19782 && !hscrolling_current_line_p (w));
19783
19784 beg_unchanged = BEG_UNCHANGED;
19785 end_unchanged = END_UNCHANGED;
19786
19787 SET_TEXT_POS (opoint, PT, PT_BYTE);
19788
19789 specbind (Qinhibit_point_motion_hooks, Qt);
19790
19791 buffer_unchanged_p
19792 = (w->window_end_valid
19793 && !current_buffer->clip_changed
19794 && !window_outdated (w));
19795
19796
19797
19798 if (windows_or_buffers_changed)
19799 {
19800
19801
19802 if (XMARKER (w->start)->buffer == current_buffer)
19803 compute_window_start_on_continuation_line (w);
19804
19805 w->window_end_valid = false;
19806
19807
19808 current_matrix_up_to_date_p = false;
19809 }
19810
19811
19812 CHECK_WINDOW_END (w);
19813 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19814 emacs_abort ();
19815 if (BYTEPOS (opoint) < CHARPOS (opoint))
19816 emacs_abort ();
19817
19818 if (mode_line_update_needed (w))
19819 update_mode_line = true;
19820
19821
19822
19823 if (!EQ (window, selected_window))
19824 {
19825 ptrdiff_t new_pt = marker_position (w->pointm);
19826 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19827
19828 if (new_pt < BEGV)
19829 {
19830 new_pt = BEGV;
19831 new_pt_byte = BEGV_BYTE;
19832 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19833 }
19834 else if (new_pt > (ZV - 1))
19835 {
19836 new_pt = ZV;
19837 new_pt_byte = ZV_BYTE;
19838 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19839 }
19840
19841
19842 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19843 }
19844
19845
19846
19847
19848
19849
19850 if (current_buffer->width_run_cache
19851 || (current_buffer->base_buffer
19852 && current_buffer->base_buffer->width_run_cache))
19853 {
19854 struct Lisp_Char_Table *disptab = buffer_display_table ();
19855
19856 if (! disptab_matches_widthtab
19857 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19858 {
19859 struct buffer *buf = current_buffer;
19860
19861 if (buf->base_buffer)
19862 buf = buf->base_buffer;
19863 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19864 recompute_width_table (current_buffer, disptab);
19865 }
19866 }
19867
19868
19869 if (!NILP (Vlong_line_threshold)
19870 && !current_buffer->long_line_optimizations_p
19871 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19872 || current_buffer->clip_changed))
19873 {
19874 ptrdiff_t cur, next, found, max = 0, threshold;
19875 threshold = XFIXNUM (Vlong_line_threshold);
19876 for (cur = BEGV; cur < ZV; cur = next)
19877 {
19878 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19879 &found, NULL, true);
19880 if (next - cur > max) max = next - cur;
19881 if (!found || max > threshold) break;
19882 }
19883 if (max > threshold)
19884 current_buffer->long_line_optimizations_p = true;
19885 }
19886
19887
19888 if (XMARKER (w->start)->buffer != current_buffer)
19889 goto recenter;
19890
19891 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19892
19893
19894
19895 if ((w->optional_new_start || window_frozen_p (w))
19896 && CHARPOS (startp) >= BEGV
19897 && CHARPOS (startp) <= ZV)
19898 {
19899 ptrdiff_t it_charpos;
19900
19901 w->optional_new_start = false;
19902 if (!w->force_start)
19903 {
19904 start_display (&it, w, startp);
19905 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19906 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19907
19908
19909 it_charpos = IT_CHARPOS (it);
19910
19911
19912
19913
19914
19915 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19916 {
19917 if (it_charpos == PT)
19918 w->force_start = true;
19919
19920 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19921 w->force_start = true;
19922 #ifdef GLYPH_DEBUG
19923 if (w->force_start)
19924 {
19925 if (window_frozen_p (w))
19926 debug_method_add (w, "set force_start from frozen window start");
19927 else
19928 debug_method_add (w, "set force_start from optional_new_start");
19929 }
19930 #endif
19931 }
19932 }
19933 }
19934
19935 force_start:
19936
19937
19938
19939 if (w->force_start)
19940 {
19941
19942 int new_vpos = -1;
19943
19944 w->force_start = false;
19945
19946
19947
19948
19949 if (!w->preserve_vscroll_p || !window_frozen_p (w))
19950 w->vscroll = 0;
19951
19952 w->preserve_vscroll_p = false;
19953 w->window_end_valid = false;
19954
19955
19956 if (!buffer_unchanged_p)
19957 w->base_line_number = 0;
19958
19959
19960
19961
19962
19963
19964
19965
19966 if (!update_mode_line
19967 || ! NILP (Vwindow_scroll_functions))
19968 {
19969 update_mode_line = true;
19970 w->update_mode_line = true;
19971 startp = run_window_scroll_functions (window, startp);
19972 }
19973
19974 if (CHARPOS (startp) < BEGV)
19975 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
19976 else if (CHARPOS (startp) > ZV)
19977 SET_TEXT_POS (startp, ZV, ZV_BYTE);
19978
19979
19980
19981 if (!window_start_acceptable_p (window, CHARPOS (startp)))
19982 goto ignore_start;
19983
19984
19985
19986
19987
19988
19989 clear_glyph_matrix (w->desired_matrix);
19990 if (!try_window (window, startp, 0))
19991 {
19992 w->force_start = true;
19993 clear_glyph_matrix (w->desired_matrix);
19994 goto need_larger_matrices;
19995 }
19996
19997 if (w->cursor.vpos < 0)
19998 {
19999
20000
20001
20002
20003
20004 struct glyph_row *r = NULL;
20005 Lisp_Object invprop =
20006 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20007 Qnil, NULL);
20008
20009 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
20010 {
20011 ptrdiff_t alt_pt;
20012 Lisp_Object invprop_end =
20013 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20014 Qnil, Qnil);
20015
20016 if (FIXNATP (invprop_end))
20017 alt_pt = XFIXNAT (invprop_end);
20018 else
20019 alt_pt = ZV;
20020 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
20021 NULL, 0);
20022 }
20023 if (r)
20024 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
20025 else
20026 new_vpos = window_box_height (w) / 2;
20027 }
20028
20029 if (!cursor_row_fully_visible_p (w, false, false, false))
20030 {
20031
20032
20033 new_vpos = window_box_height (w);
20034
20035
20036
20037
20038
20039
20040 if (new_vpos >= w->cursor.y)
20041 {
20042 w->cursor.vpos = -1;
20043 clear_glyph_matrix (w->desired_matrix);
20044 goto try_to_scroll;
20045 }
20046 }
20047 else if (w->cursor.vpos >= 0)
20048 {
20049
20050
20051
20052 int pixel_margin = margin * frame_line_height;
20053 bool tab_line = window_wants_tab_line (w);
20054 bool header_line = window_wants_header_line (w);
20055
20056
20057
20058
20059
20060 if (w->cursor.vpos < margin + tab_line + header_line)
20061 {
20062 w->cursor.vpos = -1;
20063 clear_glyph_matrix (w->desired_matrix);
20064 goto try_to_scroll;
20065 }
20066 else
20067 {
20068 int window_height = window_box_height (w);
20069
20070 if (tab_line)
20071 window_height += CURRENT_TAB_LINE_HEIGHT (w);
20072 if (header_line)
20073 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
20074 if (w->cursor.y >= window_height - pixel_margin)
20075 {
20076 w->cursor.vpos = -1;
20077 clear_glyph_matrix (w->desired_matrix);
20078 goto try_to_scroll;
20079 }
20080 }
20081 }
20082
20083
20084
20085 if (new_vpos >= 0)
20086 {
20087 struct glyph_row *row;
20088
20089 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
20090 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
20091 && !row->ends_at_zv_p)
20092 ++row;
20093
20094 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
20095 MATRIX_ROW_START_BYTEPOS (row));
20096
20097 if (w != XWINDOW (selected_window))
20098 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
20099 else if (current_buffer == old)
20100 SET_TEXT_POS (lpoint, PT, PT_BYTE);
20101
20102 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
20103
20104
20105
20106
20107
20108
20109
20110 w->redisplay = false;
20111 XBUFFER (w->contents)->text->redisplay = false;
20112 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
20113
20114 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
20115 || ((EQ (Vdisplay_line_numbers, Qrelative)
20116 || EQ (Vdisplay_line_numbers, Qvisual))
20117 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
20118 {
20119
20120
20121
20122
20123 clear_glyph_matrix (w->desired_matrix);
20124 if (!try_window (window, startp, 0))
20125 goto need_larger_matrices;
20126 }
20127 }
20128 if (w->cursor.vpos < 0
20129 || !cursor_row_fully_visible_p (w, false, false, false))
20130 {
20131 clear_glyph_matrix (w->desired_matrix);
20132 goto try_to_scroll;
20133 }
20134
20135 #ifdef GLYPH_DEBUG
20136 debug_method_add (w, "forced window start");
20137 #endif
20138 goto done;
20139 }
20140
20141 ignore_start:
20142
20143
20144
20145
20146 if (current_matrix_up_to_date_p
20147 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
20148 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
20149 {
20150 switch (rc)
20151 {
20152 case CURSOR_MOVEMENT_SUCCESS:
20153 used_current_matrix_p = true;
20154 goto done;
20155
20156 case CURSOR_MOVEMENT_MUST_SCROLL:
20157 goto try_to_scroll;
20158
20159 default:
20160 emacs_abort ();
20161 }
20162 }
20163
20164
20165
20166 else if (w->start_at_line_beg
20167 && ((CHARPOS (startp) > BEGV
20168 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
20169 || (CHARPOS (startp) >= BEGV
20170 && CHARPOS (startp) <= ZV
20171 && !window_start_acceptable_p (window, CHARPOS (startp)))))
20172 {
20173 #ifdef GLYPH_DEBUG
20174 debug_method_add (w, "recenter 1");
20175 #endif
20176 goto recenter;
20177 }
20178
20179
20180
20181
20182 else if ((tem = try_window_id (w)) != 0)
20183 {
20184 #ifdef GLYPH_DEBUG
20185 debug_method_add (w, "try_window_id %d", tem);
20186 #endif
20187
20188 if (f->fonts_changed)
20189 goto need_larger_matrices;
20190 if (tem > 0)
20191 goto done;
20192
20193
20194
20195 }
20196 else if (CHARPOS (startp) >= BEGV
20197 && CHARPOS (startp) <= ZV
20198 && PT >= CHARPOS (startp)
20199 && (CHARPOS (startp) < ZV
20200
20201 || CHARPOS (startp) == BEGV
20202 || !window_outdated (w)))
20203 {
20204 int d1, d2, d5, d6;
20205 int rtop, rbot;
20206
20207
20208
20209
20210
20211
20212
20213
20214
20215
20216 if (!w->start_at_line_beg
20217 && NILP (track_mouse)
20218 && CHARPOS (startp) > BEGV
20219 && CHARPOS (startp) > BEG + beg_unchanged
20220 && CHARPOS (startp) <= Z - end_unchanged
20221
20222
20223
20224
20225
20226 && XMARKER (w->start)->buffer == current_buffer
20227 && compute_window_start_on_continuation_line (w)
20228
20229
20230
20231
20232
20233
20234 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20235
20236
20237 && (rtop != 0) == (rbot != 0))
20238 {
20239 w->force_start = true;
20240 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20241 #ifdef GLYPH_DEBUG
20242 debug_method_add (w, "recomputed window start in continuation line");
20243 #endif
20244 goto force_start;
20245 }
20246
20247
20248
20249
20250 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20251 {
20252 #ifdef GLYPH_DEBUG
20253 debug_method_add (w, "recenter 2");
20254 #endif
20255 goto recenter;
20256 }
20257
20258 #ifdef GLYPH_DEBUG
20259 debug_method_add (w, "same window start");
20260 #endif
20261
20262
20263
20264 if (!current_matrix_up_to_date_p
20265
20266
20267
20268 || !NILP (Vwindow_scroll_functions)
20269 || MINI_WINDOW_P (w)
20270 || !(used_current_matrix_p
20271 = try_window_reusing_current_matrix (w)))
20272 {
20273 IF_DEBUG (debug_method_add (w, "1"));
20274 clear_glyph_matrix (w->desired_matrix);
20275 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20276
20277
20278
20279 goto try_to_scroll;
20280 }
20281
20282 if (f->fonts_changed)
20283 goto need_larger_matrices;
20284
20285 if (w->cursor.vpos >= 0)
20286 {
20287 if (!just_this_one_p
20288 || current_buffer->clip_changed
20289 || BEG_UNCHANGED < CHARPOS (startp))
20290
20291 w->base_line_number = 0;
20292
20293 if (!cursor_row_fully_visible_p (w, true, false, false))
20294 {
20295 clear_glyph_matrix (w->desired_matrix);
20296 last_line_misfit = true;
20297 }
20298
20299 else
20300 goto done;
20301 }
20302 else
20303 clear_glyph_matrix (w->desired_matrix);
20304 }
20305
20306 try_to_scroll:
20307
20308
20309 if (!update_mode_line)
20310 {
20311 update_mode_line = true;
20312 w->update_mode_line = true;
20313 }
20314
20315
20316 if ((0 < scroll_conservatively
20317
20318
20319
20320
20321 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20322 || 0 < emacs_scroll_step
20323 || temp_scroll_step
20324 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20325 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20326 && CHARPOS (startp) >= BEGV
20327 && CHARPOS (startp) <= ZV)
20328 {
20329
20330
20331 int ss = try_scrolling (window, just_this_one_p,
20332 ((scroll_minibuffer_conservatively
20333 && MINI_WINDOW_P (w))
20334 ? SCROLL_LIMIT + 1
20335 : scroll_conservatively),
20336 emacs_scroll_step,
20337 temp_scroll_step, last_line_misfit);
20338 switch (ss)
20339 {
20340 case SCROLLING_SUCCESS:
20341 goto done;
20342
20343 case SCROLLING_NEED_LARGER_MATRICES:
20344 goto need_larger_matrices;
20345
20346 case SCROLLING_FAILED:
20347 break;
20348
20349 default:
20350 emacs_abort ();
20351 }
20352 }
20353
20354
20355
20356
20357 recenter:
20358
20359 #ifdef GLYPH_DEBUG
20360 debug_method_add (w, "recenter");
20361 #endif
20362
20363
20364 if (!buffer_unchanged_p)
20365 w->base_line_number = 0;
20366
20367
20368 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20369 it.current_y = it.last_visible_y;
20370 if (centering_position < 0)
20371 {
20372 ptrdiff_t margin_pos = CHARPOS (startp);
20373 Lisp_Object aggressive;
20374 bool scrolling_up;
20375
20376
20377
20378 if (margin
20379
20380
20381
20382
20383
20384
20385 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20386 {
20387 struct it it1;
20388 void *it1data = NULL;
20389
20390 SAVE_IT (it1, it, it1data);
20391 start_display (&it1, w, startp);
20392 move_it_vertically (&it1, margin * frame_line_height);
20393 margin_pos = IT_CHARPOS (it1);
20394 RESTORE_IT (&it, &it, it1data);
20395 }
20396 scrolling_up = PT > margin_pos;
20397 aggressive =
20398 scrolling_up
20399 ? BVAR (current_buffer, scroll_up_aggressively)
20400 : BVAR (current_buffer, scroll_down_aggressively);
20401
20402 if (!MINI_WINDOW_P (w)
20403 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20404 {
20405 int pt_offset = 0;
20406
20407
20408
20409 if (!scroll_conservatively && NUMBERP (aggressive))
20410 {
20411 double float_amount = XFLOATINT (aggressive);
20412
20413 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20414 if (pt_offset == 0 && float_amount > 0)
20415 pt_offset = 1;
20416 if (pt_offset && margin > 0)
20417 margin -= 1;
20418 }
20419
20420
20421
20422 if (scrolling_up)
20423 {
20424 centering_position = it.last_visible_y;
20425 if (pt_offset)
20426 centering_position -= pt_offset;
20427 centering_position -=
20428 (frame_line_height * (1 + margin + last_line_misfit)
20429 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20430
20431
20432 if (centering_position < margin * frame_line_height)
20433 centering_position = margin * frame_line_height;
20434 }
20435 else
20436 centering_position = margin * frame_line_height + pt_offset;
20437 }
20438 else
20439
20440
20441 centering_position = window_box_height (w) / 2;
20442 }
20443 if (current_buffer->long_line_optimizations_p
20444 && it.line_wrap == TRUNCATE)
20445 {
20446
20447
20448
20449 int nlines = centering_position / frame_line_height;
20450
20451 while (nlines-- && IT_CHARPOS (it) > BEGV)
20452 back_to_previous_visible_line_start (&it);
20453 reseat_1 (&it, it.current.pos, true);
20454 }
20455 else
20456 move_it_vertically_backward (&it, centering_position);
20457
20458 eassert (IT_CHARPOS (it) >= BEGV);
20459
20460
20461
20462
20463
20464
20465 if (it.current_y <= 0)
20466 {
20467 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20468 move_it_vertically_backward (&it, 0);
20469 it.current_y = 0;
20470 }
20471
20472 it.current_x = it.hpos = 0;
20473
20474
20475
20476
20477 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20478
20479
20480 startp = run_window_scroll_functions (window, it.current.pos);
20481
20482
20483
20484
20485 itdata = bidi_shelve_cache ();
20486
20487
20488 use_desired_matrix = false;
20489 if (!current_matrix_up_to_date_p
20490 || windows_or_buffers_changed
20491 || f->cursor_type_changed
20492
20493
20494 || !NILP (Vwindow_scroll_functions)
20495 || !just_this_one_p
20496 || MINI_WINDOW_P (w)
20497 || !(used_current_matrix_p
20498 = try_window_reusing_current_matrix (w)))
20499 use_desired_matrix = (try_window (window, startp, 0) == 1);
20500
20501 bidi_unshelve_cache (itdata, false);
20502
20503
20504
20505
20506 if (f->fonts_changed)
20507 goto need_larger_matrices;
20508
20509
20510
20511
20512
20513
20514 if (w->cursor.vpos < 0)
20515 {
20516 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20517 {
20518 clear_glyph_matrix (w->desired_matrix);
20519 move_it_by_lines (&it, 1);
20520 try_window (window, it.current.pos, 0);
20521 }
20522 else if (PT < IT_CHARPOS (it))
20523 {
20524 clear_glyph_matrix (w->desired_matrix);
20525 move_it_by_lines (&it, -1);
20526 try_window (window, it.current.pos, 0);
20527 }
20528 else if (scroll_conservatively > SCROLL_LIMIT
20529 && (it.method == GET_FROM_STRING
20530 || overlay_touches_p (IT_CHARPOS (it)))
20531 && IT_CHARPOS (it) < ZV)
20532 {
20533
20534
20535
20536
20537
20538
20539
20540
20541 ptrdiff_t pos0 = IT_CHARPOS (it);
20542
20543 clear_glyph_matrix (w->desired_matrix);
20544 do {
20545 move_it_by_lines (&it, 1);
20546 } while (IT_CHARPOS (it) == pos0);
20547 try_window (window, it.current.pos, 0);
20548 }
20549 else
20550 {
20551
20552 }
20553 }
20554
20555
20556
20557
20558
20559
20560 if (w->cursor.vpos < 0)
20561 {
20562
20563
20564
20565
20566 struct glyph_matrix *matrix =
20567 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20568
20569 struct glyph_row *row =
20570 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20571
20572
20573
20574
20575
20576
20577
20578 if (!row)
20579 {
20580 Lisp_Object val =
20581 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20582 Qnil, NULL);
20583
20584 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20585 {
20586 ptrdiff_t alt_pos;
20587 Lisp_Object invis_end =
20588 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20589 Qnil, Qnil);
20590
20591 if (FIXNATP (invis_end))
20592 alt_pos = XFIXNAT (invis_end);
20593 else
20594 alt_pos = ZV;
20595 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20596 }
20597 }
20598
20599
20600
20601 if (!row)
20602 {
20603 row = matrix->rows;
20604
20605 if (row->tab_line_p)
20606 ++row;
20607 if (row->mode_line_p)
20608 ++row;
20609 }
20610 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20611 }
20612
20613 if (!cursor_row_fully_visible_p (w, false, false, false))
20614 {
20615
20616 if (w->vscroll)
20617 {
20618 w->vscroll = 0;
20619 clear_glyph_matrix (w->desired_matrix);
20620 goto recenter;
20621 }
20622
20623
20624
20625
20626
20627 if (scroll_conservatively > SCROLL_LIMIT)
20628 {
20629 int window_total_lines
20630 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20631 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20632
20633 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20634 clear_glyph_matrix (w->desired_matrix);
20635 if (1 == try_window (window, it.current.pos,
20636 TRY_WINDOW_CHECK_MARGINS))
20637 goto done;
20638 }
20639
20640
20641
20642
20643 if (centering_position == 0)
20644 goto done;
20645
20646 clear_glyph_matrix (w->desired_matrix);
20647 centering_position = 0;
20648 goto recenter;
20649 }
20650
20651 done:
20652
20653 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20654 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20655 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20656
20657
20658 if ((update_mode_line
20659
20660
20661
20662
20663 || (!just_this_one_p
20664 && !FRAME_WINDOW_P (f)
20665 && !WINDOW_FULL_WIDTH_P (w))
20666
20667 || w->base_line_pos > 0
20668
20669 || (w->column_number_displayed != -1
20670 && (w->column_number_displayed != current_column ())))
20671
20672 && (window_wants_mode_line (w)
20673 || window_wants_header_line (w)
20674 || window_wants_tab_line (w)))
20675 {
20676 specpdl_ref count1 = SPECPDL_INDEX ();
20677
20678 specbind (Qinhibit_quit, Qt);
20679 display_mode_lines (w);
20680 unbind_to (count1, Qnil);
20681
20682
20683
20684 if (window_wants_mode_line (w)
20685 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20686 {
20687 f->fonts_changed = true;
20688 w->mode_line_height = -1;
20689 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20690 = DESIRED_MODE_LINE_HEIGHT (w);
20691 }
20692
20693
20694
20695 if (window_wants_tab_line (w)
20696 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20697 {
20698 f->fonts_changed = true;
20699 w->tab_line_height = -1;
20700 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20701 = DESIRED_TAB_LINE_HEIGHT (w);
20702 }
20703
20704
20705
20706 if (window_wants_header_line (w)
20707 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20708 {
20709 f->fonts_changed = true;
20710 w->header_line_height = -1;
20711 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20712 = DESIRED_HEADER_LINE_HEIGHT (w);
20713 }
20714
20715 if (f->fonts_changed)
20716 goto need_larger_matrices;
20717 }
20718
20719 if (!line_number_displayed && w->base_line_pos != -1)
20720 {
20721 w->base_line_pos = 0;
20722 w->base_line_number = 0;
20723 }
20724
20725 finish_menu_bars:
20726
20727
20728
20729 if (update_mode_line
20730 && EQ (FRAME_SELECTED_WINDOW (f), window))
20731 {
20732 bool redisplay_menu_p;
20733
20734 if (FRAME_WINDOW_P (f))
20735 {
20736 #ifdef HAVE_EXT_MENU_BAR
20737 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20738 #else
20739 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20740 #endif
20741 }
20742 else
20743 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20744
20745 if (redisplay_menu_p)
20746 display_menu_bar (w);
20747
20748 #ifdef HAVE_WINDOW_SYSTEM
20749 if (FRAME_WINDOW_P (f))
20750 {
20751 if (WINDOWP (f->tab_bar_window)
20752 && (FRAME_TAB_BAR_LINES (f) > 0
20753 || !NILP (Vauto_resize_tab_bars))
20754 && redisplay_tab_bar (f))
20755 ignore_mouse_drag_p = true;
20756
20757 #ifdef HAVE_EXT_TOOL_BAR
20758 if (FRAME_EXTERNAL_TOOL_BAR (f))
20759 update_frame_tool_bar (f);
20760 #else
20761 if (WINDOWP (f->tool_bar_window)
20762 && (FRAME_TOOL_BAR_LINES (f) > 0
20763 || !NILP (Vauto_resize_tool_bars))
20764 && redisplay_tool_bar (f))
20765 ignore_mouse_drag_p = true;
20766 #endif
20767 }
20768 else
20769 {
20770 if ((FRAME_TAB_BAR_LINES (f) > 0))
20771 display_tab_bar (w);
20772 }
20773
20774 gui_consider_frame_title (w->frame);
20775 #else
20776 if ((FRAME_TAB_BAR_LINES (f) > 0))
20777 display_tab_bar (w);
20778 #endif
20779 }
20780
20781 #ifdef HAVE_WINDOW_SYSTEM
20782 if (FRAME_WINDOW_P (f)
20783 && update_window_fringes (w, (just_this_one_p
20784 || (!used_current_matrix_p && !overlay_arrow_seen)
20785 || w->pseudo_window_p)))
20786 {
20787 update_begin (f);
20788 block_input ();
20789 if (draw_window_fringes (w, true))
20790 {
20791 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20792 gui_draw_right_divider (w);
20793 else
20794 gui_draw_vertical_border (w);
20795 }
20796 unblock_input ();
20797 update_end (f);
20798 }
20799
20800 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20801 gui_draw_bottom_divider (w);
20802 #endif
20803
20804
20805
20806
20807
20808 need_larger_matrices:
20809 ;
20810 finish_scroll_bars:
20811
20812 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20813 {
20814 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20815
20816 set_vertical_scroll_bar (w);
20817
20818 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20819
20820 set_horizontal_scroll_bar (w);
20821
20822
20823
20824 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20825 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20826 }
20827
20828
20829
20830
20831 if (CHARPOS (opoint) < BEGV)
20832 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20833 else if (CHARPOS (opoint) > ZV)
20834 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20835 else
20836 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20837
20838 set_buffer_internal_1 (old);
20839
20840
20841 if (CHARPOS (lpoint) <= ZV)
20842 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20843
20844 unbind_to (count, Qnil);
20845 }
20846
20847
20848
20849
20850
20851
20852
20853
20854
20855
20856
20857
20858
20859
20860
20861
20862
20863
20864
20865
20866 int
20867 try_window (Lisp_Object window, struct text_pos pos, int flags)
20868 {
20869 struct window *w = XWINDOW (window);
20870 struct it it;
20871 struct glyph_row *last_text_row = NULL;
20872 struct frame *f = XFRAME (w->frame);
20873 int cursor_vpos = w->cursor.vpos;
20874
20875
20876 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20877
20878
20879 w->cursor.vpos = -1;
20880 overlay_arrow_seen = false;
20881
20882
20883 start_display (&it, w, pos);
20884 it.glyph_row->reversed_p = false;
20885
20886
20887 while (it.current_y < it.last_visible_y)
20888 {
20889 int last_row_scale = it.w->nrows_scale_factor;
20890 int last_col_scale = it.w->ncols_scale_factor;
20891 if (display_line (&it, cursor_vpos))
20892 last_text_row = it.glyph_row - 1;
20893 if (f->fonts_changed
20894 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20895
20896
20897 && last_row_scale == it.w->nrows_scale_factor
20898 && last_col_scale == it.w->ncols_scale_factor))
20899 return 0;
20900 }
20901
20902
20903
20904 ptrdiff_t it_charpos = IT_CHARPOS (it);
20905
20906
20907
20908
20909 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20910 && w->vscroll == 0
20911 && !MINI_WINDOW_P (w))
20912 {
20913 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20914 int bot_scroll_margin = top_scroll_margin;
20915 if (window_wants_header_line (w))
20916 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20917 if (window_wants_tab_line (w))
20918 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20919 start_display (&it, w, pos);
20920
20921 if ((w->cursor.y >= 0
20922 && w->cursor.y < top_scroll_margin
20923 && CHARPOS (pos) > BEGV)
20924
20925
20926
20927
20928 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20929 - bot_scroll_margin - 1))
20930 {
20931 w->cursor.vpos = -1;
20932 clear_glyph_matrix (w->desired_matrix);
20933 return -1;
20934 }
20935 }
20936
20937
20938 if (w->window_end_pos <= 0 && Z != it_charpos)
20939 w->update_mode_line = true;
20940
20941
20942
20943
20944 if (last_text_row)
20945 {
20946 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
20947 adjust_window_ends (w, last_text_row, false);
20948 eassert
20949 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
20950 w->window_end_vpos)));
20951 }
20952 else
20953 {
20954 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
20955 w->window_end_pos = Z - ZV;
20956 w->window_end_vpos = 0;
20957 }
20958
20959
20960 w->window_end_valid = false;
20961 return 1;
20962 }
20963
20964
20965
20966
20967
20968
20969
20970
20971
20972
20973
20974
20975 static bool
20976 try_window_reusing_current_matrix (struct window *w)
20977 {
20978 struct frame *f = XFRAME (w->frame);
20979 struct glyph_row *bottom_row;
20980 struct it it;
20981 struct run run;
20982 struct text_pos start, new_start;
20983 int nrows_scrolled, i;
20984 struct glyph_row *last_text_row;
20985 struct glyph_row *last_reused_text_row;
20986 struct glyph_row *start_row;
20987 int start_vpos, min_y, max_y;
20988
20989 #ifdef GLYPH_DEBUG
20990 if (inhibit_try_window_reusing)
20991 return false;
20992 #endif
20993
20994 if (
20995 !FRAME_WINDOW_P (f)
20996
20997
20998 || windows_or_buffers_changed
20999 || f->cursor_type_changed
21000
21001
21002
21003 || overlay_arrow_in_current_buffer_p ())
21004 return false;
21005
21006
21007 if (!NILP (Vshow_trailing_whitespace))
21008 return false;
21009
21010
21011 if (window_wants_tab_line (w)
21012 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
21013 return false;
21014
21015
21016 if (window_wants_header_line (w)
21017 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
21018 return false;
21019
21020
21021
21022 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21023 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
21024 return false;
21025
21026
21027 clear_glyph_matrix (w->desired_matrix);
21028
21029
21030
21031
21032 if (!NILP (Vdisplay_line_numbers))
21033 return false;
21034
21035
21036
21037
21038 #ifdef HAVE_NTGUI
21039 if (w32_use_visible_system_caret)
21040 return false;
21041 #endif
21042
21043
21044
21045 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
21046 start = start_row->minpos;
21047 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21048
21049 if (CHARPOS (new_start) <= CHARPOS (start))
21050 {
21051
21052
21053
21054
21055 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
21056 return false;
21057
21058 IF_DEBUG (debug_method_add (w, "twu1"));
21059
21060
21061
21062
21063
21064 start_display (&it, w, new_start);
21065 w->cursor.vpos = -1;
21066 last_text_row = last_reused_text_row = NULL;
21067
21068 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21069 {
21070
21071
21072
21073
21074 while (IT_CHARPOS (it) > CHARPOS (start))
21075 {
21076
21077 start_row++;
21078 start = start_row->minpos;
21079
21080 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
21081 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
21082 || CHARPOS (start) == ZV)
21083 {
21084 clear_glyph_matrix (w->desired_matrix);
21085 return false;
21086 }
21087
21088 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21089 }
21090
21091
21092 if (IT_CHARPOS (it) == CHARPOS (start)
21093
21094
21095
21096
21097
21098 && it.current.dpvec_index < 0)
21099 break;
21100
21101 it.glyph_row->reversed_p = false;
21102 if (display_line (&it, -1))
21103 last_text_row = it.glyph_row - 1;
21104
21105 }
21106
21107
21108
21109
21110 if (it.current_y < it.last_visible_y)
21111 {
21112 struct glyph_row *row;
21113
21114
21115 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
21116
21117
21118 if (w->cursor.vpos < 0)
21119 {
21120 int dy = it.current_y - start_row->y;
21121
21122 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21123 row = row_containing_pos (w, PT, row, NULL, dy);
21124 if (row)
21125 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
21126 dy, nrows_scrolled);
21127 else
21128 {
21129 clear_glyph_matrix (w->desired_matrix);
21130 return false;
21131 }
21132 }
21133
21134
21135
21136
21137
21138
21139
21140 run.current_y = start_row->y;
21141 run.desired_y = it.current_y;
21142 run.height = it.last_visible_y - it.current_y;
21143
21144 if (run.height > 0 && run.current_y != run.desired_y)
21145 {
21146 #ifdef HAVE_WINDOW_SYSTEM
21147 update_begin (f);
21148 gui_update_window_begin (w);
21149 FRAME_RIF (f)->clear_window_mouse_face (w);
21150 FRAME_RIF (f)->scroll_run_hook (w, &run);
21151 gui_update_window_end (w, false, false);
21152 update_end (f);
21153 #endif
21154 }
21155
21156
21157 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21158 rotate_matrix (w->current_matrix,
21159 start_vpos,
21160 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21161 nrows_scrolled);
21162
21163
21164 for (i = 0; i < nrows_scrolled; ++i)
21165 (start_row + i)->enabled_p = false;
21166
21167
21168 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21169 max_y = it.last_visible_y;
21170 for (row = start_row + nrows_scrolled;
21171 row < bottom_row;
21172 ++row)
21173 {
21174 row->y = it.current_y;
21175 row->visible_height = row->height;
21176
21177 if (row->y < min_y)
21178 row->visible_height -= min_y - row->y;
21179 if (row->y + row->height > max_y)
21180 row->visible_height -= row->y + row->height - max_y;
21181 if (row->fringe_bitmap_periodic_p)
21182 row->redraw_fringe_bitmaps_p = true;
21183
21184 it.current_y += row->height;
21185
21186 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21187 last_reused_text_row = row;
21188 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21189 break;
21190 }
21191
21192
21193
21194 for (++row; row < bottom_row; ++row)
21195 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21196 }
21197
21198
21199
21200
21201
21202 if (last_reused_text_row)
21203 adjust_window_ends (w, last_reused_text_row, true);
21204 else if (last_text_row)
21205 adjust_window_ends (w, last_text_row, false);
21206 else
21207 {
21208
21209 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21210 w->window_end_pos = Z - ZV;
21211 w->window_end_vpos = 0;
21212 }
21213 w->window_end_valid = false;
21214
21215
21216 w->desired_matrix->no_scrolling_p = true;
21217
21218 #ifdef GLYPH_DEBUG
21219 debug_method_add (w, "try_window_reusing_current_matrix 1");
21220 #endif
21221 return true;
21222 }
21223 else if (CHARPOS (new_start) > CHARPOS (start))
21224 {
21225 struct glyph_row *pt_row, *row;
21226 struct glyph_row *first_reusable_row;
21227 struct glyph_row *first_row_to_display;
21228 int dy;
21229 int yb = window_text_bottom_y (w);
21230
21231
21232
21233 first_reusable_row = start_row;
21234 while (first_reusable_row->enabled_p
21235 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21236 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21237 < CHARPOS (new_start)))
21238 ++first_reusable_row;
21239
21240
21241 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21242 || !first_reusable_row->enabled_p
21243 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21244 != CHARPOS (new_start)))
21245 return false;
21246
21247
21248
21249
21250
21251 pt_row = NULL;
21252 for (first_row_to_display = first_reusable_row;
21253 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21254 ++first_row_to_display)
21255 {
21256 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21257 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21258 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21259 && first_row_to_display->ends_at_zv_p
21260 && pt_row == NULL)))
21261 pt_row = first_row_to_display;
21262 }
21263
21264 if (first_row_to_display->y >= yb)
21265 return false;
21266
21267
21268 init_to_row_start (&it, w, first_row_to_display);
21269
21270 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21271 - start_vpos);
21272 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21273 - nrows_scrolled);
21274 it.current_y = (first_row_to_display->y - first_reusable_row->y
21275 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21276
21277
21278
21279
21280 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21281 if (pt_row == NULL)
21282 w->cursor.vpos = -1;
21283 last_text_row = NULL;
21284 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21285 if (display_line (&it, w->cursor.vpos))
21286 last_text_row = it.glyph_row - 1;
21287
21288
21289
21290 if (pt_row)
21291 {
21292 w->cursor.vpos -= nrows_scrolled;
21293 w->cursor.y -= first_reusable_row->y - start_row->y;
21294 }
21295
21296
21297
21298
21299
21300 if (w->cursor.vpos < 0)
21301 {
21302 clear_glyph_matrix (w->desired_matrix);
21303 return false;
21304 }
21305
21306
21307 run.current_y = first_reusable_row->y;
21308 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21309 run.height = it.last_visible_y - run.current_y;
21310 dy = run.current_y - run.desired_y;
21311
21312 if (run.height)
21313 {
21314 #ifdef HAVE_WINDOW_SYSTEM
21315 update_begin (f);
21316 gui_update_window_begin (w);
21317 FRAME_RIF (f)->clear_window_mouse_face (w);
21318 FRAME_RIF (f)->scroll_run_hook (w, &run);
21319 gui_update_window_end (w, false, false);
21320 update_end (f);
21321 #endif
21322 }
21323
21324
21325 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21326 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21327 max_y = it.last_visible_y;
21328 for (row = first_reusable_row; row < first_row_to_display; ++row)
21329 {
21330 row->y -= dy;
21331 row->visible_height = row->height;
21332 if (row->y < min_y)
21333 row->visible_height -= min_y - row->y;
21334 if (row->y + row->height > max_y)
21335 row->visible_height -= row->y + row->height - max_y;
21336 if (row->fringe_bitmap_periodic_p)
21337 row->redraw_fringe_bitmaps_p = true;
21338 }
21339
21340
21341 eassert (nrows_scrolled > 0);
21342 rotate_matrix (w->current_matrix,
21343 start_vpos,
21344 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21345 -nrows_scrolled);
21346
21347
21348 for (row -= nrows_scrolled; row < bottom_row; ++row)
21349 row->enabled_p = false;
21350
21351
21352
21353 if (pt_row)
21354 {
21355 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21356 row < bottom_row
21357 && PT >= MATRIX_ROW_END_CHARPOS (row)
21358 && !row->ends_at_zv_p;
21359 row++)
21360 {
21361 w->cursor.vpos++;
21362 w->cursor.y = row->y;
21363 }
21364 if (row < bottom_row)
21365 {
21366
21367
21368
21369
21370 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21371 {
21372 if (!set_cursor_from_row (w, row, w->current_matrix,
21373 0, 0, 0, 0))
21374 {
21375 clear_glyph_matrix (w->desired_matrix);
21376 return false;
21377 }
21378 }
21379 else
21380 {
21381 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21382 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21383
21384 for (; glyph < end
21385 && (!BUFFERP (glyph->object)
21386 || glyph->charpos < PT);
21387 glyph++)
21388 {
21389 w->cursor.hpos++;
21390 w->cursor.x += glyph->pixel_width;
21391 }
21392 }
21393 }
21394 }
21395
21396
21397
21398
21399 if (last_text_row)
21400 adjust_window_ends (w, last_text_row, false);
21401 else
21402 w->window_end_vpos -= nrows_scrolled;
21403
21404 w->window_end_valid = false;
21405 w->desired_matrix->no_scrolling_p = true;
21406
21407 #ifdef GLYPH_DEBUG
21408 debug_method_add (w, "try_window_reusing_current_matrix 2");
21409 #endif
21410 return true;
21411 }
21412
21413 return false;
21414 }
21415
21416
21417
21418
21419
21420
21421
21422 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21423 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21424 ptrdiff_t *, ptrdiff_t *);
21425 static struct glyph_row *
21426 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21427 struct glyph_row *);
21428
21429
21430
21431
21432
21433
21434
21435 static struct glyph_row *
21436 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21437 struct glyph_row *start)
21438 {
21439 struct glyph_row *row, *row_found;
21440
21441
21442
21443
21444 row_found = NULL;
21445 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21446 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21447 {
21448 eassert (row->enabled_p);
21449 row_found = row;
21450 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21451 break;
21452 ++row;
21453 }
21454
21455 return row_found;
21456 }
21457
21458
21459
21460
21461
21462
21463
21464
21465
21466
21467
21468
21469 static struct glyph_row *
21470 find_last_unchanged_at_beg_row (struct window *w)
21471 {
21472 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21473 struct glyph_row *row;
21474 struct glyph_row *row_found = NULL;
21475 int yb = window_text_bottom_y (w);
21476
21477
21478 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21479 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21480 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21481 ++row)
21482 {
21483 if (
21484
21485 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21486
21487
21488 && !row->ends_at_zv_p
21489
21490
21491
21492 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21493 && (row->continued_p
21494 || row->exact_window_width_line_p))
21495
21496
21497
21498
21499
21500
21501
21502 && CHARPOS (row->end.pos) <= ZV)
21503 row_found = row;
21504
21505
21506 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21507 break;
21508 }
21509
21510 return row_found;
21511 }
21512
21513
21514
21515
21516
21517
21518
21519
21520
21521
21522
21523
21524
21525
21526 static struct glyph_row *
21527 find_first_unchanged_at_end_row (struct window *w,
21528 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21529 {
21530 struct glyph_row *row;
21531 struct glyph_row *row_found = NULL;
21532
21533 *delta = *delta_bytes = 0;
21534
21535
21536
21537 eassert (w->window_end_valid);
21538
21539
21540
21541
21542 if (w->window_end_pos >= END_UNCHANGED)
21543 return NULL;
21544
21545
21546 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21547
21548
21549 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21550 {
21551
21552
21553
21554
21555
21556 ptrdiff_t Z_old =
21557 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21558 ptrdiff_t Z_BYTE_old =
21559 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21560 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21561 struct glyph_row *first_text_row
21562 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21563
21564 *delta = Z - Z_old;
21565 *delta_bytes = Z_BYTE - Z_BYTE_old;
21566
21567
21568
21569
21570
21571
21572
21573 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21574 last_unchanged_pos_old = last_unchanged_pos - *delta;
21575
21576
21577
21578 for (; row > first_text_row; --row)
21579 {
21580
21581
21582 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21583 break;
21584
21585 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21586 row_found = row;
21587 }
21588 }
21589
21590 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21591
21592 return row_found;
21593 }
21594
21595
21596
21597
21598
21599
21600
21601
21602 static void
21603 sync_frame_with_window_matrix_rows (struct window *w)
21604 {
21605 struct frame *f = XFRAME (w->frame);
21606 struct glyph_row *window_row, *window_row_end, *frame_row;
21607
21608
21609
21610 eassert (BUFFERP (w->contents));
21611 eassert (WINDOW_FULL_WIDTH_P (w));
21612 eassert (!FRAME_WINDOW_P (f));
21613
21614
21615
21616
21617
21618 window_row = w->current_matrix->rows;
21619 window_row_end = window_row + w->current_matrix->nrows;
21620 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21621 while (window_row < window_row_end)
21622 {
21623 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21624 struct glyph *end = window_row->glyphs[LAST_AREA];
21625
21626 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21627 frame_row->glyphs[TEXT_AREA] = start;
21628 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21629 frame_row->glyphs[LAST_AREA] = end;
21630
21631
21632
21633 if (!window_row->enabled_p)
21634 frame_row->enabled_p = false;
21635
21636 ++window_row, ++frame_row;
21637 }
21638 }
21639
21640
21641
21642
21643
21644
21645
21646 struct glyph_row *
21647 row_containing_pos (struct window *w, ptrdiff_t charpos,
21648 struct glyph_row *start, struct glyph_row *end, int dy)
21649 {
21650 struct glyph_row *row = start;
21651 struct glyph_row *best_row = NULL;
21652 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21653 int last_y;
21654
21655
21656 if (row->tab_line_p)
21657 ++row;
21658 if (row->mode_line_p)
21659 ++row;
21660
21661 if ((end && row >= end) || !row->enabled_p)
21662 return NULL;
21663
21664 last_y = window_text_bottom_y (w) - dy;
21665
21666 while (true)
21667 {
21668
21669 if ((end && row >= end) || !row->enabled_p)
21670 return NULL;
21671
21672
21673
21674 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21675 return NULL;
21676
21677
21678 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21679 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21680
21681
21682
21683
21684 && !row_for_charpos_p (row, charpos)))
21685 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21686 {
21687 struct glyph *g;
21688
21689 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21690 || (!best_row && !row->continued_p))
21691 return row;
21692
21693
21694
21695
21696 for (g = row->glyphs[TEXT_AREA];
21697 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21698 g++)
21699 {
21700 if (!STRINGP (g->object))
21701 {
21702 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21703 {
21704 mindif = eabs (g->charpos - charpos);
21705 best_row = row;
21706
21707 if (mindif == 0)
21708 return best_row;
21709 }
21710 }
21711 }
21712 }
21713 else if (best_row && !row->continued_p)
21714 return best_row;
21715 ++row;
21716 }
21717 }
21718
21719
21720
21721
21722
21723
21724
21725
21726
21727
21728
21729
21730
21731
21732
21733
21734
21735
21736
21737
21738
21739
21740
21741
21742
21743
21744
21745
21746
21747
21748
21749
21750
21751
21752
21753
21754
21755
21756
21757
21758
21759
21760
21761
21762 static int
21763 try_window_id (struct window *w)
21764 {
21765 struct frame *f = XFRAME (w->frame);
21766 struct glyph_matrix *current_matrix = w->current_matrix;
21767 struct glyph_matrix *desired_matrix = w->desired_matrix;
21768 struct glyph_row *last_unchanged_at_beg_row;
21769 struct glyph_row *first_unchanged_at_end_row;
21770 struct glyph_row *row;
21771 struct glyph_row *bottom_row;
21772 int bottom_vpos;
21773 struct it it;
21774 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21775 int dvpos, dy;
21776 struct text_pos start_pos;
21777 struct run run;
21778 int first_unchanged_at_end_vpos = 0;
21779 struct glyph_row *last_text_row, *last_text_row_at_end;
21780 struct text_pos start;
21781 ptrdiff_t first_changed_charpos, last_changed_charpos;
21782
21783 #ifdef GLYPH_DEBUG
21784 if (inhibit_try_window_id)
21785 return 0;
21786 #endif
21787
21788
21789 #if false
21790 #define GIVE_UP(X) \
21791 do { \
21792 redisplay_trace ("try_window_id give up %d\n", X); \
21793 return 0; \
21794 } while (false)
21795 #else
21796 #define GIVE_UP(X) return 0
21797 #endif
21798
21799 SET_TEXT_POS_FROM_MARKER (start, w->start);
21800
21801
21802
21803 if (MINI_WINDOW_P (w))
21804 GIVE_UP (1);
21805
21806
21807 if (windows_or_buffers_changed || f->cursor_type_changed)
21808 GIVE_UP (2);
21809
21810
21811
21812
21813 if (w->last_overlay_modified != OVERLAY_MODIFF)
21814 GIVE_UP (200);
21815
21816
21817
21818
21819
21820 if (current_buffer->clip_changed
21821 || current_buffer->prevent_redisplay_optimizations_p)
21822 GIVE_UP (3);
21823
21824
21825 if (!FRAME_WINDOW_P (f)
21826 && (!FRAME_LINE_INS_DEL_OK (f)
21827 || !WINDOW_FULL_WIDTH_P (w)))
21828 GIVE_UP (4);
21829
21830
21831 if (PT < CHARPOS (start))
21832 GIVE_UP (5);
21833
21834
21835 if (w->last_modified == 0)
21836 GIVE_UP (6);
21837
21838
21839 if (w->hscroll != 0)
21840 GIVE_UP (7);
21841
21842
21843 if (!w->window_end_valid)
21844 GIVE_UP (8);
21845
21846
21847 if (!NILP (Vshow_trailing_whitespace))
21848 GIVE_UP (11);
21849
21850
21851
21852 if (overlay_arrows_changed_p (false))
21853 GIVE_UP (12);
21854
21855
21856
21857
21858
21859 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21860 GIVE_UP (21);
21861
21862
21863
21864
21865
21866
21867
21868
21869
21870 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21871 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21872 GIVE_UP (22);
21873
21874
21875
21876 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21877 GIVE_UP (23);
21878
21879
21880
21881 if (EQ (Vdisplay_line_numbers, Qrelative)
21882 || EQ (Vdisplay_line_numbers, Qvisual)
21883 || (!NILP (Vdisplay_line_numbers)
21884 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21885 Qline_number_current_line,
21886 w->frame))))
21887 GIVE_UP (24);
21888
21889
21890
21891
21892 if (composition_break_at_point)
21893 GIVE_UP (27);
21894
21895
21896
21897
21898
21899 if (MODIFF > SAVE_MODIFF
21900
21901 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21902 {
21903 if (GPT - BEG < BEG_UNCHANGED)
21904 BEG_UNCHANGED = GPT - BEG;
21905 if (Z - GPT < END_UNCHANGED)
21906 END_UNCHANGED = Z - GPT;
21907 }
21908
21909
21910 first_changed_charpos = BEG + BEG_UNCHANGED;
21911 last_changed_charpos = Z - END_UNCHANGED;
21912
21913
21914
21915
21916
21917
21918 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21919 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21920 && ((last_changed_charpos < CHARPOS (start)
21921 && CHARPOS (start) == BEGV)
21922 || (last_changed_charpos < CHARPOS (start) - 1
21923 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21924 {
21925 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21926 struct glyph_row *r0;
21927
21928
21929
21930 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21931 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21932 Z_delta = Z - Z_old;
21933 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
21934
21935
21936
21937
21938 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
21939 GIVE_UP (13);
21940
21941
21942
21943
21944 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21945 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
21946 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
21947
21948 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
21949 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21950 {
21951
21952 if (Z_delta || Z_delta_bytes)
21953 {
21954 struct glyph_row *r1
21955 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
21956 increment_matrix_positions (w->current_matrix,
21957 MATRIX_ROW_VPOS (r0, current_matrix),
21958 MATRIX_ROW_VPOS (r1, current_matrix),
21959 Z_delta, Z_delta_bytes);
21960 }
21961
21962
21963 row = row_containing_pos (w, PT, r0, NULL, 0);
21964 if (row)
21965 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21966 return 1;
21967 }
21968 }
21969
21970
21971
21972
21973
21974 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
21975
21976
21977 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
21978 || first_changed_charpos == last_changed_charpos))
21979 {
21980 struct glyph_row *r0;
21981
21982
21983
21984
21985 if (PT >= MATRIX_ROW_END_CHARPOS (row))
21986 GIVE_UP (14);
21987
21988
21989
21990
21991 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21992 if (TEXT_POS_EQUAL_P (start, r0->minpos)
21993
21994 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
21995 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21996 {
21997
21998
21999 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22000 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22001
22002
22003 row = row_containing_pos (w, PT, r0, NULL, 0);
22004 if (row)
22005 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
22006 return 2;
22007 }
22008 }
22009
22010
22011
22012
22013
22014
22015
22016
22017 if (CHARPOS (start) >= first_changed_charpos
22018 && CHARPOS (start) <= last_changed_charpos)
22019 GIVE_UP (15);
22020
22021
22022
22023
22024
22025 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
22026 if (!TEXT_POS_EQUAL_P (start, row->minpos))
22027 GIVE_UP (16);
22028
22029
22030
22031 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
22032 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
22033 GIVE_UP (20);
22034
22035
22036
22037
22038
22039 #ifdef HAVE_NTGUI
22040 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
22041 GIVE_UP (25);
22042 #endif
22043
22044
22045
22046
22047
22048
22049
22050 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
22051 if (last_unchanged_at_beg_row)
22052 {
22053
22054
22055
22056
22057 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
22058 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
22059 && last_unchanged_at_beg_row > w->current_matrix->rows)
22060 --last_unchanged_at_beg_row;
22061
22062 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
22063 GIVE_UP (17);
22064
22065 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
22066 GIVE_UP (18);
22067
22068
22069
22070 if (it.sp > 1
22071 && it.method == GET_FROM_IMAGE && it.image_id == -1)
22072 GIVE_UP (26);
22073 start_pos = it.current.pos;
22074
22075
22076
22077
22078 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
22079 current_matrix);
22080 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22081 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
22082
22083 eassert (it.hpos == 0 && it.current_x == 0);
22084 }
22085 else
22086 {
22087
22088
22089 start_display (&it, w, start);
22090 it.vpos = it.first_vpos;
22091 start_pos = it.current.pos;
22092 }
22093
22094
22095
22096
22097
22098
22099
22100 first_unchanged_at_end_row
22101 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
22102 IF_DEBUG (debug_delta = delta);
22103 IF_DEBUG (debug_delta_bytes = delta_bytes);
22104
22105
22106
22107
22108
22109
22110 stop_pos = 0;
22111 if (first_unchanged_at_end_row)
22112 {
22113 eassert (last_unchanged_at_beg_row == NULL
22114 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
22115
22116
22117
22118
22119
22120 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
22121 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22122 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22123 < it.last_visible_y))
22124 ++first_unchanged_at_end_row;
22125
22126 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22127 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22128 >= it.last_visible_y))
22129 first_unchanged_at_end_row = NULL;
22130 else
22131 {
22132 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
22133 + delta);
22134 first_unchanged_at_end_vpos
22135 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
22136 eassert (stop_pos >= Z - END_UNCHANGED);
22137 }
22138 }
22139 else if (last_unchanged_at_beg_row == NULL)
22140 GIVE_UP (19);
22141
22142
22143 #ifdef GLYPH_DEBUG
22144
22145
22146
22147
22148 eassert (first_unchanged_at_end_row == NULL
22149 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22150
22151 debug_last_unchanged_at_beg_vpos
22152 = (last_unchanged_at_beg_row
22153 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
22154 : -1);
22155 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
22156
22157 #endif
22158
22159
22160
22161
22162
22163 w->cursor.vpos = -1;
22164 last_text_row = NULL;
22165 overlay_arrow_seen = false;
22166 if (it.current_y < it.last_visible_y
22167 && !f->fonts_changed
22168 && (first_unchanged_at_end_row == NULL
22169 || IT_CHARPOS (it) < stop_pos))
22170 it.glyph_row->reversed_p = false;
22171 while (it.current_y < it.last_visible_y
22172 && !f->fonts_changed
22173 && (first_unchanged_at_end_row == NULL
22174 || IT_CHARPOS (it) < stop_pos))
22175 {
22176 if (display_line (&it, -1))
22177 last_text_row = it.glyph_row - 1;
22178 }
22179
22180 if (f->fonts_changed)
22181 return -1;
22182
22183
22184
22185
22186
22187
22188
22189
22190
22191
22192
22193 if (!w->window_end_valid)
22194 {
22195 clear_glyph_matrix (w->desired_matrix);
22196 return -1;
22197 }
22198
22199
22200
22201
22202 if (first_unchanged_at_end_row
22203
22204
22205 && it.current_y < it.last_visible_y)
22206 {
22207 dvpos = (it.vpos
22208 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22209 current_matrix));
22210 dy = it.current_y - first_unchanged_at_end_row->y;
22211 run.current_y = first_unchanged_at_end_row->y;
22212 run.desired_y = run.current_y + dy;
22213 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22214 }
22215 else
22216 {
22217 delta = delta_bytes = dvpos = dy
22218 = run.current_y = run.desired_y = run.height = 0;
22219 first_unchanged_at_end_row = NULL;
22220 }
22221 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22222
22223
22224
22225
22226
22227
22228
22229
22230
22231
22232 if (w->cursor.vpos < 0)
22233 {
22234
22235 if (PT < CHARPOS (start_pos)
22236 && last_unchanged_at_beg_row)
22237 {
22238 row = row_containing_pos (w, PT,
22239 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22240 last_unchanged_at_beg_row + 1, 0);
22241 if (row)
22242 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22243 }
22244
22245
22246 else if (first_unchanged_at_end_row)
22247 {
22248 row = row_containing_pos (w, PT - delta,
22249 first_unchanged_at_end_row, NULL, 0);
22250 if (row)
22251 set_cursor_from_row (w, row, w->current_matrix, delta,
22252 delta_bytes, dy, dvpos);
22253 }
22254
22255
22256 if (w->cursor.vpos < 0)
22257 {
22258 clear_glyph_matrix (w->desired_matrix);
22259 return -1;
22260 }
22261 }
22262
22263
22264 {
22265 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22266 int bot_scroll_margin = top_scroll_margin;
22267 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22268
22269 if (window_wants_header_line (w))
22270 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22271 if (window_wants_tab_line (w))
22272 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22273
22274 if ((w->cursor.y < top_scroll_margin
22275 && CHARPOS (start) > BEGV)
22276
22277
22278 || (w->cursor.y
22279 + (cursor_row_fully_visible_p (w, false, true, true)
22280 ? 1
22281 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22282 {
22283 w->cursor.vpos = -1;
22284 clear_glyph_matrix (w->desired_matrix);
22285 return -1;
22286 }
22287 }
22288
22289
22290
22291
22292 if (dy && run.height)
22293 {
22294 update_begin (f);
22295
22296 if (FRAME_WINDOW_P (f))
22297 {
22298 #ifdef HAVE_WINDOW_SYSTEM
22299 gui_update_window_begin (w);
22300 FRAME_RIF (f)->clear_window_mouse_face (w);
22301 FRAME_RIF (f)->scroll_run_hook (w, &run);
22302 gui_update_window_end (w, false, false);
22303 #endif
22304 }
22305 else
22306 {
22307
22308
22309 int from_vpos
22310 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22311 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22312 int end = (WINDOW_TOP_EDGE_LINE (w)
22313 + window_wants_tab_line (w)
22314 + window_wants_header_line (w)
22315 + window_internal_height (w));
22316
22317 gui_clear_window_mouse_face (w);
22318
22319
22320 if (dvpos > 0)
22321 {
22322
22323
22324 set_terminal_window (f, end);
22325
22326
22327
22328 if (!FRAME_SCROLL_REGION_OK (f))
22329 ins_del_lines (f, end - dvpos, -dvpos);
22330
22331
22332
22333 ins_del_lines (f, from, dvpos);
22334 }
22335 else if (dvpos < 0)
22336 {
22337
22338
22339 set_terminal_window (f, end);
22340
22341
22342
22343
22344
22345 ins_del_lines (f, from + dvpos, dvpos);
22346
22347
22348
22349 if (!FRAME_SCROLL_REGION_OK (f))
22350 ins_del_lines (f, end + dvpos, -dvpos);
22351 }
22352
22353 set_terminal_window (f, 0);
22354 }
22355
22356 update_end (f);
22357 }
22358
22359
22360
22361
22362 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22363 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22364 if (dvpos < 0)
22365 {
22366 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22367 bottom_vpos, dvpos);
22368 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22369 bottom_vpos);
22370 }
22371 else if (dvpos > 0)
22372 {
22373 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22374 bottom_vpos, dvpos);
22375 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22376 first_unchanged_at_end_vpos + dvpos);
22377 }
22378
22379
22380
22381 if (!FRAME_WINDOW_P (f))
22382 sync_frame_with_window_matrix_rows (w);
22383
22384
22385 if (delta || delta_bytes)
22386 increment_matrix_positions (current_matrix,
22387 first_unchanged_at_end_vpos + dvpos,
22388 bottom_vpos, delta, delta_bytes);
22389
22390
22391 if (dy)
22392 shift_glyph_matrix (w, current_matrix,
22393 first_unchanged_at_end_vpos + dvpos,
22394 bottom_vpos, dy);
22395
22396 if (first_unchanged_at_end_row)
22397 {
22398 first_unchanged_at_end_row += dvpos;
22399 if (first_unchanged_at_end_row->y >= it.last_visible_y
22400 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22401 first_unchanged_at_end_row = NULL;
22402 }
22403
22404
22405
22406 last_text_row_at_end = NULL;
22407 if (dy < 0)
22408 {
22409
22410
22411
22412
22413
22414 int last_vpos = w->window_end_vpos + dvpos;
22415 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22416
22417
22418 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22419
22420
22421
22422
22423 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22424 {
22425 init_to_row_start (&it, w, last_row);
22426 it.vpos = last_vpos;
22427 it.current_y = last_row->y;
22428 }
22429 else
22430 {
22431 init_to_row_end (&it, w, last_row);
22432 it.vpos = 1 + last_vpos;
22433 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22434 ++last_row;
22435 }
22436
22437
22438
22439 it.continuation_lines_width = last_row->continuation_lines_width;
22440 it.hpos = it.current_x = 0;
22441
22442
22443 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22444 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22445 {
22446
22447
22448
22449
22450 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22451 if (display_line (&it, w->cursor.vpos))
22452 last_text_row_at_end = it.glyph_row - 1;
22453 }
22454 }
22455
22456
22457 if (first_unchanged_at_end_row && !last_text_row_at_end)
22458 {
22459
22460
22461
22462
22463 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22464 row = find_last_row_displaying_text (w->current_matrix, &it,
22465 first_unchanged_at_end_row);
22466 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22467 adjust_window_ends (w, row, true);
22468 eassert (w->window_end_bytepos >= 0);
22469 IF_DEBUG (debug_method_add (w, "A"));
22470 }
22471 else if (last_text_row_at_end)
22472 {
22473 adjust_window_ends (w, last_text_row_at_end, false);
22474 eassert (w->window_end_bytepos >= 0);
22475 IF_DEBUG (debug_method_add (w, "B"));
22476 }
22477 else if (last_text_row)
22478 {
22479
22480
22481
22482 adjust_window_ends (w, last_text_row, false);
22483 eassert (w->window_end_bytepos >= 0);
22484 }
22485 else if (first_unchanged_at_end_row == NULL
22486 && last_text_row == NULL
22487 && last_text_row_at_end == NULL)
22488 {
22489
22490
22491 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22492 int vpos = w->window_end_vpos;
22493 struct glyph_row *current_row = current_matrix->rows + vpos;
22494 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22495
22496 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22497 {
22498 eassert (first_vpos <= vpos);
22499 if (desired_row->enabled_p)
22500 {
22501 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22502 row = desired_row;
22503 }
22504 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22505 row = current_row;
22506 }
22507
22508 w->window_end_vpos = vpos + 1;
22509 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22510 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22511 eassert (w->window_end_bytepos >= 0);
22512 IF_DEBUG (debug_method_add (w, "C"));
22513 }
22514 else
22515 emacs_abort ();
22516
22517 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22518 debug_end_vpos = w->window_end_vpos));
22519
22520
22521 w->window_end_valid = false;
22522 w->desired_matrix->no_scrolling_p = true;
22523 return 3;
22524
22525 #undef GIVE_UP
22526 }
22527
22528
22529
22530
22531
22532
22533
22534 #ifdef GLYPH_DEBUG
22535
22536 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22537 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22538 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22539
22540
22541
22542
22543
22544
22545
22546
22547 void
22548 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22549 {
22550 int i;
22551 for (i = 0; i < matrix->nrows; ++i)
22552 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22553 }
22554
22555
22556
22557
22558
22559 void
22560 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22561 {
22562 if (glyph->type == CHAR_GLYPH
22563 || glyph->type == GLYPHLESS_GLYPH)
22564 {
22565 fprintf (stderr,
22566 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22567 glyph - row->glyphs[TEXT_AREA],
22568 (glyph->type == CHAR_GLYPH
22569 ? 'C'
22570 : 'G'),
22571 glyph->charpos,
22572 (BUFFERP (glyph->object)
22573 ? 'B'
22574 : (STRINGP (glyph->object)
22575 ? 'S'
22576 : (NILP (glyph->object)
22577 ? '0'
22578 : '-'))),
22579 glyph->pixel_width,
22580 glyph->u.ch,
22581 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22582 ? (int) glyph->u.ch
22583 : '.'),
22584 glyph->face_id,
22585 glyph->left_box_line_p,
22586 glyph->right_box_line_p);
22587 }
22588 else if (glyph->type == STRETCH_GLYPH)
22589 {
22590 fprintf (stderr,
22591 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22592 glyph - row->glyphs[TEXT_AREA],
22593 'S',
22594 glyph->charpos,
22595 (BUFFERP (glyph->object)
22596 ? 'B'
22597 : (STRINGP (glyph->object)
22598 ? 'S'
22599 : (NILP (glyph->object)
22600 ? '0'
22601 : '-'))),
22602 glyph->pixel_width,
22603 0u,
22604 ' ',
22605 glyph->face_id,
22606 glyph->left_box_line_p,
22607 glyph->right_box_line_p);
22608 }
22609 else if (glyph->type == IMAGE_GLYPH)
22610 {
22611 fprintf (stderr,
22612 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22613 glyph - row->glyphs[TEXT_AREA],
22614 'I',
22615 glyph->charpos,
22616 (BUFFERP (glyph->object)
22617 ? 'B'
22618 : (STRINGP (glyph->object)
22619 ? 'S'
22620 : (NILP (glyph->object)
22621 ? '0'
22622 : '-'))),
22623 glyph->pixel_width,
22624 (unsigned int) glyph->u.img_id,
22625 '.',
22626 glyph->face_id,
22627 glyph->left_box_line_p,
22628 glyph->right_box_line_p);
22629 }
22630 else if (glyph->type == COMPOSITE_GLYPH)
22631 {
22632 fprintf (stderr,
22633 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22634 glyph - row->glyphs[TEXT_AREA],
22635 '+',
22636 glyph->charpos,
22637 (BUFFERP (glyph->object)
22638 ? 'B'
22639 : (STRINGP (glyph->object)
22640 ? 'S'
22641 : (NILP (glyph->object)
22642 ? '0'
22643 : '-'))),
22644 glyph->pixel_width,
22645 (unsigned int) glyph->u.cmp.id);
22646 if (glyph->u.cmp.automatic)
22647 fprintf (stderr,
22648 "[%d-%d]",
22649 glyph->slice.cmp.from, glyph->slice.cmp.to);
22650 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22651 glyph->face_id,
22652 glyph->left_box_line_p,
22653 glyph->right_box_line_p);
22654 }
22655 else if (glyph->type == XWIDGET_GLYPH)
22656 {
22657 #ifndef HAVE_XWIDGETS
22658 eassume (false);
22659 #else
22660 fprintf (stderr,
22661 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22662 glyph - row->glyphs[TEXT_AREA],
22663 'X',
22664 glyph->charpos,
22665 (BUFFERP (glyph->object)
22666 ? 'B'
22667 : (STRINGP (glyph->object)
22668 ? 'S'
22669 : '-')),
22670 glyph->pixel_width,
22671 glyph->u.xwidget,
22672 '.',
22673 glyph->face_id,
22674 glyph->left_box_line_p,
22675 glyph->right_box_line_p);
22676 #endif
22677 }
22678 }
22679
22680
22681
22682
22683
22684
22685
22686 void
22687 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22688 {
22689 if (glyphs != 1)
22690 {
22691 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22692 "==============================================================================\n"),
22693 stderr);
22694 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22695 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22696 vpos,
22697 MATRIX_ROW_START_CHARPOS (row),
22698 MATRIX_ROW_END_CHARPOS (row),
22699 row->used[TEXT_AREA],
22700 row->contains_overlapping_glyphs_p,
22701 row->enabled_p,
22702 row->truncated_on_left_p,
22703 row->truncated_on_right_p,
22704 row->continued_p,
22705 MATRIX_ROW_CONTINUATION_LINE_P (row),
22706 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22707 row->ends_at_zv_p,
22708 row->fill_line_p,
22709 row->ends_in_middle_of_char_p,
22710 row->starts_in_middle_of_char_p,
22711 row->mouse_face_p,
22712 row->x,
22713 row->y,
22714 row->pixel_width,
22715 row->height,
22716 row->visible_height,
22717 row->ascent,
22718 row->phys_ascent);
22719
22720 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22721 row->end.overlay_string_index,
22722 row->continuation_lines_width);
22723 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22724 CHARPOS (row->start.string_pos),
22725 CHARPOS (row->end.string_pos));
22726 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22727 row->end.dpvec_index);
22728 }
22729
22730 if (glyphs > 1)
22731 {
22732 int area;
22733
22734 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22735 {
22736 struct glyph *glyph = row->glyphs[area];
22737 struct glyph *glyph_end = glyph + row->used[area];
22738
22739
22740 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22741 ++glyph_end;
22742
22743 if (glyph < glyph_end)
22744 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22745 stderr);
22746
22747 for (; glyph < glyph_end; ++glyph)
22748 dump_glyph (row, glyph, area);
22749 }
22750 }
22751 else if (glyphs == 1)
22752 {
22753 int area;
22754 char s[SHRT_MAX + 4];
22755
22756 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22757 {
22758 int i;
22759
22760 for (i = 0; i < row->used[area]; ++i)
22761 {
22762 struct glyph *glyph = row->glyphs[area] + i;
22763 if (i == row->used[area] - 1
22764 && area == TEXT_AREA
22765 && NILP (glyph->object)
22766 && glyph->type == CHAR_GLYPH
22767 && glyph->u.ch == ' ')
22768 {
22769 strcpy (&s[i], "[\\n]");
22770 i += 4;
22771 }
22772 else if (glyph->type == CHAR_GLYPH
22773 && glyph->u.ch < 0x80
22774 && glyph->u.ch >= ' ')
22775 s[i] = glyph->u.ch;
22776 else
22777 s[i] = '.';
22778 }
22779
22780 s[i] = '\0';
22781 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22782 }
22783 }
22784 }
22785
22786
22787 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22788 Sdump_glyph_matrix, 0, 1, "p",
22789 doc:
22790
22791
22792
22793
22794
22795 )
22796 (Lisp_Object glyphs)
22797 {
22798 struct window *w = XWINDOW (selected_window);
22799 struct buffer *buffer = XBUFFER (w->contents);
22800
22801 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22802 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22803 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22804 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22805 fputs ("=============================================\n", stderr);
22806 dump_glyph_matrix (w->current_matrix,
22807 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22808 return Qnil;
22809 }
22810
22811
22812 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22813 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22814 )
22815 (void)
22816 {
22817 struct frame *f = XFRAME (selected_frame);
22818
22819 if (f->current_matrix)
22820 dump_glyph_matrix (f->current_matrix, 1);
22821 else
22822 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22823 return Qnil;
22824 }
22825
22826
22827 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22828 doc:
22829
22830
22831
22832
22833 )
22834 (Lisp_Object row, Lisp_Object glyphs)
22835 {
22836 struct glyph_matrix *matrix;
22837 EMACS_INT vpos;
22838
22839 if (NILP (row))
22840 {
22841 int d1, d2, d3, d4, d5, ypos;
22842 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22843 &d1, &d2, &d3, &d4, &d5, &ypos);
22844 if (visible_p)
22845 vpos = ypos;
22846 else
22847 vpos = 0;
22848 }
22849 else
22850 {
22851 CHECK_FIXNUM (row);
22852 vpos = XFIXNUM (row);
22853 }
22854 matrix = XWINDOW (selected_window)->current_matrix;
22855 if (vpos >= 0 && vpos < matrix->nrows)
22856 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22857 vpos,
22858 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22859 return Qnil;
22860 }
22861
22862
22863 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22864 doc:
22865
22866
22867
22868
22869
22870
22871 )
22872 (Lisp_Object row, Lisp_Object glyphs)
22873 {
22874 #if defined (HAVE_WINDOW_SYSTEM)
22875 struct frame *sf = SELECTED_FRAME ();
22876 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22877 ? XWINDOW (sf->tab_bar_window)->current_matrix
22878 : sf->current_matrix;
22879 EMACS_INT vpos;
22880
22881 if (NILP (row))
22882 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22883 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22884 else
22885 {
22886 CHECK_FIXNUM (row);
22887 vpos = XFIXNUM (row);
22888 }
22889 if (vpos >= 0 && vpos < m->nrows)
22890 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22891 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22892 #endif
22893 return Qnil;
22894 }
22895
22896 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22897 doc:
22898
22899
22900
22901
22902
22903
22904 )
22905 (Lisp_Object row, Lisp_Object glyphs)
22906 {
22907 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22908 struct frame *sf = SELECTED_FRAME ();
22909 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22910 EMACS_INT vpos;
22911
22912 if (NILP (row))
22913 vpos = 0;
22914 else
22915 {
22916 CHECK_FIXNUM (row);
22917 vpos = XFIXNUM (row);
22918 }
22919 if (vpos >= 0 && vpos < m->nrows)
22920 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22921 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22922 #endif
22923 return Qnil;
22924 }
22925
22926
22927 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22928 doc:
22929 )
22930 (Lisp_Object arg)
22931 {
22932 if (NILP (arg))
22933 trace_redisplay_p = !trace_redisplay_p;
22934 else
22935 {
22936 arg = Fprefix_numeric_value (arg);
22937 trace_redisplay_p = XFIXNUM (arg) > 0;
22938 }
22939
22940 return Qnil;
22941 }
22942
22943
22944 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
22945 doc:
22946 )
22947 (ptrdiff_t nargs, Lisp_Object *args)
22948 {
22949 Lisp_Object s = Fformat (nargs, args);
22950 fwrite (SDATA (s), 1, SBYTES (s), stderr);
22951 return Qnil;
22952 }
22953
22954 #endif
22955
22956
22957
22958
22959
22960
22961
22962
22963
22964
22965
22966 static struct glyph_row *
22967 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
22968 {
22969 struct frame *f = XFRAME (WINDOW_FRAME (w));
22970 struct buffer *buffer = XBUFFER (w->contents);
22971 struct buffer *old = current_buffer;
22972 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
22973 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
22974 const unsigned char *arrow_end = arrow_string + arrow_len;
22975 const unsigned char *p;
22976 struct it it;
22977 bool multibyte_p;
22978 int n_glyphs_before;
22979
22980 set_buffer_temp (buffer);
22981 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
22982 scratch_glyph_row.reversed_p = false;
22983 it.glyph_row->used[TEXT_AREA] = 0;
22984 SET_TEXT_POS (it.position, 0, 0);
22985
22986 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
22987 p = arrow_string;
22988 while (p < arrow_end)
22989 {
22990 Lisp_Object face, ilisp;
22991
22992
22993 if (multibyte_p)
22994 it.c = it.char_to_display = check_char_and_length (p, &it.len);
22995 else
22996 {
22997 it.c = it.char_to_display = *p, it.len = 1;
22998 if (! ASCII_CHAR_P (it.c))
22999 it.char_to_display = BYTE8_TO_CHAR (it.c);
23000 }
23001 p += it.len;
23002
23003
23004 ilisp = make_fixnum (char_num++);
23005 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
23006 it.face_id = compute_char_face (f, it.char_to_display, face);
23007
23008
23009 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
23010 SET_TEXT_POS (it.position, -1, -1);
23011 PRODUCE_GLYPHS (&it);
23012
23013
23014
23015 if (it.current_x > it.last_visible_x)
23016 {
23017 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
23018 break;
23019 }
23020 }
23021
23022 set_buffer_temp (old);
23023 return it.glyph_row;
23024 }
23025
23026
23027
23028
23029
23030 static void
23031 insert_left_trunc_glyphs (struct it *it)
23032 {
23033 struct it truncate_it;
23034 struct glyph *from, *end, *to, *toend;
23035
23036 eassert (!FRAME_WINDOW_P (it->f)
23037 || (!it->glyph_row->reversed_p
23038 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23039 || (it->glyph_row->reversed_p
23040 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
23041
23042
23043 truncate_it = *it;
23044 truncate_it.current_x = 0;
23045 truncate_it.face_id = DEFAULT_FACE_ID;
23046 truncate_it.glyph_row = &scratch_glyph_row;
23047 truncate_it.area = TEXT_AREA;
23048 truncate_it.glyph_row->used[TEXT_AREA] = 0;
23049 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
23050 truncate_it.object = Qnil;
23051 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
23052
23053
23054 if (!it->glyph_row->reversed_p)
23055 {
23056 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23057
23058 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23059 end = from + tused;
23060 to = it->glyph_row->glyphs[TEXT_AREA];
23061 toend = to + it->glyph_row->used[TEXT_AREA];
23062 if (FRAME_WINDOW_P (it->f))
23063 {
23064
23065
23066
23067
23068
23069
23070
23071 int w = 0;
23072 struct glyph *g = to;
23073 short used;
23074
23075
23076
23077
23078
23079
23080 it->glyph_row->x = 0;
23081 while (g < toend && w < it->truncation_pixel_width)
23082 {
23083 w += g->pixel_width;
23084 ++g;
23085 }
23086 if (g - to - tused > 0)
23087 {
23088 memmove (to + tused, g, (toend - g) * sizeof(*g));
23089 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
23090 }
23091 used = it->glyph_row->used[TEXT_AREA];
23092 if (it->glyph_row->truncated_on_right_p
23093 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
23094 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
23095 == STRETCH_GLYPH)
23096 {
23097 int extra = w - it->truncation_pixel_width;
23098
23099 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
23100 }
23101 }
23102
23103 while (from < end)
23104 *to++ = *from++;
23105
23106
23107 if (!FRAME_WINDOW_P (it->f))
23108 {
23109 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
23110 {
23111 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23112 while (from < end)
23113 *to++ = *from++;
23114 }
23115 }
23116
23117 if (to > toend)
23118 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
23119 }
23120 else
23121 {
23122 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23123
23124
23125
23126 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
23127 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23128 toend = it->glyph_row->glyphs[TEXT_AREA];
23129 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
23130 if (FRAME_WINDOW_P (it->f))
23131 {
23132 int w = 0;
23133 struct glyph *g = to;
23134
23135 while (g >= toend && w < it->truncation_pixel_width)
23136 {
23137 w += g->pixel_width;
23138 --g;
23139 }
23140 if (to - g - tused > 0)
23141 to = g + tused;
23142 if (it->glyph_row->truncated_on_right_p
23143 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
23144 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
23145 {
23146 int extra = w - it->truncation_pixel_width;
23147
23148 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
23149 }
23150 }
23151
23152 while (from >= end && to >= toend)
23153 *to-- = *from--;
23154 if (!FRAME_WINDOW_P (it->f))
23155 {
23156 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
23157 {
23158 from =
23159 truncate_it.glyph_row->glyphs[TEXT_AREA]
23160 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23161 while (from >= end && to >= toend)
23162 *to-- = *from--;
23163 }
23164 }
23165 if (from >= end)
23166 {
23167
23168
23169 int move_by = from - end + 1;
23170 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
23171 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
23172
23173 for ( ; g >= g0; g--)
23174 g[move_by] = *g;
23175 while (from >= end)
23176 *to-- = *from--;
23177 it->glyph_row->used[TEXT_AREA] += move_by;
23178 }
23179 }
23180 }
23181
23182
23183 unsigned
23184 row_hash (struct glyph_row *row)
23185 {
23186 int area, k;
23187 unsigned hashval = 0;
23188
23189 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23190 for (k = 0; k < row->used[area]; ++k)
23191 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23192 + row->glyphs[area][k].u.val
23193 + row->glyphs[area][k].face_id
23194 + row->glyphs[area][k].padding_p
23195 + (row->glyphs[area][k].type << 2));
23196
23197 return hashval;
23198 }
23199
23200
23201
23202
23203
23204
23205
23206
23207
23208
23209
23210
23211
23212
23213
23214
23215
23216
23217 static void
23218 compute_line_metrics (struct it *it)
23219 {
23220 struct glyph_row *row = it->glyph_row;
23221
23222 if (FRAME_WINDOW_P (it->f))
23223 {
23224 int i, min_y, max_y;
23225
23226
23227
23228
23229 if (row->height == 0)
23230 {
23231 if (it->max_ascent + it->max_descent == 0)
23232 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23233 row->ascent = it->max_ascent;
23234 row->height = it->max_ascent + it->max_descent;
23235 row->phys_ascent = it->max_phys_ascent;
23236 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23237 row->extra_line_spacing = it->max_extra_line_spacing;
23238 }
23239
23240
23241 row->pixel_width = row->x;
23242 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23243 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23244
23245 eassert (row->pixel_width >= 0);
23246 eassert (row->ascent >= 0 && row->height > 0);
23247
23248 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23249 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23250
23251
23252
23253
23254 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23255 && row->phys_ascent > row->ascent)
23256 {
23257 row->height += row->phys_ascent - row->ascent;
23258 row->ascent = row->phys_ascent;
23259 }
23260
23261
23262 row->visible_height = row->height;
23263
23264 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23265 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23266
23267 if (row->y < min_y)
23268 row->visible_height -= min_y - row->y;
23269 if (row->y + row->height > max_y)
23270 row->visible_height -= row->y + row->height - max_y;
23271 }
23272 else
23273 {
23274 row->pixel_width = row->used[TEXT_AREA];
23275 if (row->continued_p)
23276 row->pixel_width -= it->continuation_pixel_width;
23277 else if (row->truncated_on_right_p)
23278 row->pixel_width -= it->truncation_pixel_width;
23279 row->ascent = row->phys_ascent = 0;
23280 row->height = row->phys_height = row->visible_height = 1;
23281 row->extra_line_spacing = 0;
23282 }
23283
23284
23285 row->hash = row_hash (row);
23286
23287 it->max_ascent = it->max_descent = 0;
23288 it->max_phys_ascent = it->max_phys_descent = 0;
23289 }
23290
23291
23292 static void
23293 clear_position (struct it *it)
23294 {
23295 it->position.charpos = 0;
23296 it->position.bytepos = 0;
23297 }
23298
23299
23300
23301
23302
23303
23304
23305
23306
23307
23308
23309
23310
23311 static bool
23312 append_space_for_newline (struct it *it, bool default_face_p)
23313 {
23314 int n = it->glyph_row->used[TEXT_AREA];
23315
23316 if (it->glyph_row->glyphs[TEXT_AREA] + n
23317 < it->glyph_row->glyphs[1 + TEXT_AREA])
23318 {
23319
23320
23321
23322
23323 enum display_element_type saved_what = it->what;
23324 int saved_c = it->c, saved_len = it->len;
23325 int saved_char_to_display = it->char_to_display;
23326 int saved_x = it->current_x;
23327 const int saved_face_id = it->face_id;
23328 bool saved_box_end = it->end_of_box_run_p;
23329 struct text_pos saved_pos = it->position;
23330 Lisp_Object saved_object = it->object;
23331 struct face *face;
23332
23333 it->what = IT_CHARACTER;
23334 clear_position (it);
23335 it->object = Qnil;
23336 it->len = 1;
23337
23338 int char_width = 1;
23339
23340 if (default_face_p
23341 #ifdef HAVE_WINDOW_SYSTEM
23342 || FRAME_WINDOW_P (it->f)
23343 #endif
23344 )
23345 {
23346 const int local_default_face_id =
23347 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23348
23349 #ifdef HAVE_WINDOW_SYSTEM
23350 if (FRAME_WINDOW_P (it->f))
23351 {
23352 struct face *default_face
23353 = FACE_FROM_ID (it->f, local_default_face_id);
23354 struct font *font = (default_face->font
23355 ? default_face->font
23356 : FRAME_FONT (it->f));
23357 char_width = (font->average_width
23358 ? font->average_width
23359 : font->space_width);
23360 }
23361 #endif
23362 if (default_face_p)
23363 it->face_id = local_default_face_id;
23364 }
23365
23366
23367
23368
23369 const int indicator_column =
23370 fill_column_indicator_column (it, char_width);
23371 int saved_end_of_box_run = it->end_of_box_run_p;
23372 bool should_keep_end_of_box_run = false;
23373
23374 if (it->current_x == indicator_column)
23375 {
23376 it->c = it->char_to_display
23377 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23378 it->face_id
23379 = merge_faces (it->w, Qfill_column_indicator,
23380 0, saved_face_id);
23381 face = FACE_FROM_ID (it->f, it->face_id);
23382 }
23383 else
23384 {
23385 it->c = it->char_to_display = ' ';
23386
23387
23388
23389 face = FACE_FROM_ID (it->f, it->face_id);
23390 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23391
23392
23393
23394
23395 if (!(it->glyph_row->reversed_p
23396
23397
23398
23399 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23400 should_keep_end_of_box_run = true;
23401 }
23402 PRODUCE_GLYPHS (it);
23403
23404
23405 if (should_keep_end_of_box_run)
23406 it->end_of_box_run_p = saved_end_of_box_run;
23407 #ifdef HAVE_WINDOW_SYSTEM
23408 if (FRAME_WINDOW_P (it->f))
23409 {
23410
23411
23412
23413 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23414 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23415 if (n == 0)
23416 {
23417 Lisp_Object height, total_height;
23418 int extra_line_spacing = it->extra_line_spacing;
23419 int boff = font->baseline_offset;
23420
23421 if (font->vertical_centering)
23422 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23423
23424 it->object = saved_object;
23425 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23426
23427
23428 height = get_it_property (it, Qline_height);
23429 if (CONSP (height)
23430 && CONSP (XCDR (height))
23431 && NILP (XCDR (XCDR (height))))
23432 {
23433 total_height = XCAR (XCDR (height));
23434 height = XCAR (height);
23435 }
23436 else
23437 total_height = Qnil;
23438 height = calc_line_height_property (it, height, font, boff, true);
23439
23440 if (it->override_ascent >= 0)
23441 {
23442 it->ascent = it->override_ascent;
23443 it->descent = it->override_descent;
23444 boff = it->override_boff;
23445 }
23446 if (EQ (height, Qt))
23447 extra_line_spacing = 0;
23448 else
23449 {
23450 Lisp_Object spacing;
23451
23452 it->phys_ascent = it->ascent;
23453 it->phys_descent = it->descent;
23454 if (!NILP (height)
23455 && XFIXNUM (height) > it->ascent + it->descent)
23456 it->ascent = XFIXNUM (height) - it->descent;
23457
23458 if (!NILP (total_height))
23459 spacing = calc_line_height_property (it, total_height, font,
23460 boff, false);
23461 else
23462 {
23463 spacing = get_it_property (it, Qline_spacing);
23464 spacing = calc_line_height_property (it, spacing, font,
23465 boff, false);
23466 }
23467 if (FIXNUMP (spacing))
23468 {
23469 extra_line_spacing = XFIXNUM (spacing);
23470 if (!NILP (total_height))
23471 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23472 }
23473 }
23474 if (extra_line_spacing > 0)
23475 {
23476 it->descent += extra_line_spacing;
23477 if (extra_line_spacing > it->max_extra_line_spacing)
23478 it->max_extra_line_spacing = extra_line_spacing;
23479 }
23480 it->max_ascent = it->ascent;
23481 it->max_descent = it->descent;
23482
23483 it->glyph_row->height = 0;
23484 }
23485
23486 g->ascent = it->max_ascent;
23487 g->descent = it->max_descent;
23488 }
23489 #endif
23490 it->override_ascent = -1;
23491 it->constrain_row_ascent_descent_p = false;
23492 it->current_x = saved_x;
23493 it->object = saved_object;
23494 it->position = saved_pos;
23495 it->what = saved_what;
23496 it->face_id = saved_face_id;
23497 it->len = saved_len;
23498 it->c = saved_c;
23499 it->char_to_display = saved_char_to_display;
23500 it->end_of_box_run_p = saved_box_end;
23501 return true;
23502 }
23503
23504 return false;
23505 }
23506
23507
23508
23509
23510
23511
23512
23513
23514
23515 static void
23516 extend_face_to_end_of_line (struct it *it)
23517 {
23518 struct frame *f = it->f;
23519
23520
23521
23522
23523
23524
23525 if ((it->current_x >= it->last_visible_x
23526 + (!FRAME_WINDOW_P (f)
23527 && it->glyph_row->reversed_p
23528 && !it->glyph_row->continued_p))
23529
23530
23531 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23532 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23533 return;
23534
23535 specpdl_ref count = SPECPDL_INDEX ();
23536
23537
23538
23539
23540 specbind (Qinhibit_quit, Qt);
23541
23542 struct face *default_face =
23543 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23544 if (!default_face)
23545 return;
23546
23547 const int extend_face_id =
23548 (it->face_id == default_face->id || it->s != NULL)
23549 ? it->face_id
23550 : (it->glyph_row->ends_at_zv_p
23551 ? default_face->id
23552 : face_at_pos (it, LFACE_EXTEND_INDEX));
23553 unbind_to (count, Qnil);
23554
23555
23556
23557
23558 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23559 ? it->saved_face_id
23560 : extend_face_id));
23561
23562 if (FRAME_WINDOW_P (f)
23563 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23564 && face->box == FACE_NO_BOX
23565 && face->underline == FACE_NO_UNDERLINE
23566 && !face->overline_p
23567 && !face->strike_through_p
23568 && face->background == FRAME_BACKGROUND_PIXEL (f)
23569 #ifdef HAVE_WINDOW_SYSTEM
23570 && !face->stipple
23571 #endif
23572 && !it->glyph_row->reversed_p
23573 && !display_fill_column_indicator)
23574 return;
23575
23576
23577
23578 it->glyph_row->fill_line_p = true;
23579
23580 const int orig_face_id = it->face_id;
23581
23582
23583
23584
23585
23586 if (!ASCII_CHAR_P (it->c))
23587 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23588
23589
23590 #ifdef HAVE_WINDOW_SYSTEM
23591 if (FRAME_WINDOW_P (f))
23592 {
23593
23594
23595 if (it->glyph_row->used[TEXT_AREA] == 0)
23596 {
23597 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23598 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23599 it->glyph_row->used[TEXT_AREA] = 1;
23600 }
23601
23602
23603 if (!(it->glyph_row->mode_line_p
23604 || (WINDOWP (f->tab_bar_window)
23605 && it->w == XWINDOW (f->tab_bar_window))
23606 #ifndef HAVE_EXT_TOOL_BAR
23607 || (WINDOWP (f->tool_bar_window)
23608 && it->w == XWINDOW (f->tool_bar_window))
23609 #endif
23610 ))
23611 {
23612 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23613 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23614 {
23615 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23616 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23617 default_face->id;
23618 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23619 }
23620 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23621 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23622 {
23623 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23624 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23625 default_face->id;
23626 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23627 }
23628
23629 struct font *font = (default_face->font
23630 ? default_face->font
23631 : FRAME_FONT (f));
23632
23633 const int char_width = (font->average_width
23634 ? font->average_width
23635 : font->space_width);
23636
23637 const int indicator_column =
23638 fill_column_indicator_column (it, char_width);
23639
23640 const char saved_char = it->char_to_display;
23641 const struct text_pos saved_pos = it->position;
23642 const bool saved_avoid_cursor = it->avoid_cursor_p;
23643 const bool saved_box_start = it->start_of_box_run_p;
23644 Lisp_Object save_object = it->object;
23645 const int saved_face_id = it->face_id;
23646
23647 it->face_id = extend_face_id;
23648 it->avoid_cursor_p = true;
23649 it->object = Qnil;
23650
23651 const int stretch_height = it->ascent + it->descent;
23652 const int stretch_ascent =
23653 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23654
23655 if (indicator_column >= 0
23656 && indicator_column > it->current_x
23657 && indicator_column < it->last_visible_x)
23658 {
23659
23660
23661
23662
23663 const int stretch_width =
23664 indicator_column - it->current_x - char_width;
23665
23666 clear_position (it);
23667
23668
23669
23670 if (stretch_width > 0)
23671 {
23672 append_stretch_glyph (it, Qnil, stretch_width,
23673 stretch_height, stretch_ascent);
23674 }
23675
23676
23677
23678 if (it->current_x < indicator_column)
23679 {
23680 const int save_face_id = it->face_id;
23681 const int save_ascent = it->ascent;
23682 const int save_descent = it->descent;
23683 it->char_to_display
23684 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23685 it->face_id
23686 = merge_faces (it->w, Qfill_column_indicator,
23687 0, extend_face_id);
23688 PRODUCE_GLYPHS (it);
23689 it->face_id = save_face_id;
23690 it->ascent = save_ascent;
23691 it->descent = save_descent;
23692 }
23693 }
23694
23695
23696
23697 if (!it->glyph_row->reversed_p)
23698 {
23699 const int stretch_width = it->last_visible_x - it->current_x;
23700
23701 if (stretch_width > 0)
23702 {
23703 clear_position (it);
23704 append_stretch_glyph (it, Qnil, stretch_width,
23705 stretch_height, stretch_ascent);
23706 }
23707 }
23708
23709 it->char_to_display = saved_char;
23710 it->position = saved_pos;
23711 it->avoid_cursor_p = saved_avoid_cursor;
23712 it->start_of_box_run_p = saved_box_start;
23713 it->object = save_object;
23714 it->face_id = saved_face_id;
23715 }
23716 if (it->glyph_row->reversed_p)
23717 {
23718
23719
23720
23721
23722
23723 struct font *font = face->font ? face->font : FRAME_FONT (f);
23724 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23725 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23726 struct glyph *g;
23727 int row_width, stretch_ascent, stretch_width;
23728 struct text_pos saved_pos;
23729 int saved_face_id;
23730 bool saved_avoid_cursor, saved_box_start;
23731
23732 for (row_width = 0, g = row_start; g < row_end; g++)
23733 row_width += g->pixel_width;
23734
23735
23736
23737
23738 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23739 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23740 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23741 stretch_width = window_box_width (it->w, TEXT_AREA);
23742 else
23743 stretch_width = it->last_visible_x - it->first_visible_x;
23744 stretch_width -= row_width;
23745
23746 if (stretch_width > 0)
23747 {
23748 stretch_ascent =
23749 (((it->ascent + it->descent)
23750 * FONT_BASE (font)) / FONT_HEIGHT (font));
23751 saved_pos = it->position;
23752 clear_position (it);
23753 saved_avoid_cursor = it->avoid_cursor_p;
23754 it->avoid_cursor_p = true;
23755 saved_face_id = it->face_id;
23756 saved_box_start = it->start_of_box_run_p;
23757
23758
23759
23760 it->face_id = (it->glyph_row->ends_at_zv_p ?
23761 default_face->id : face->id);
23762
23763 it->start_of_box_run_p = false;
23764 append_stretch_glyph (it, Qnil, stretch_width,
23765 it->ascent + it->descent, stretch_ascent);
23766 it->position = saved_pos;
23767 it->avoid_cursor_p = saved_avoid_cursor;
23768 it->face_id = saved_face_id;
23769 it->start_of_box_run_p = saved_box_start;
23770 }
23771
23772
23773
23774
23775 if (stretch_width < 0)
23776 it->glyph_row->x = stretch_width;
23777 }
23778 it->face_id = orig_face_id;
23779 }
23780 else
23781 #endif
23782 {
23783
23784 int saved_x = it->current_x;
23785 struct text_pos saved_pos = it->position;
23786 Lisp_Object saved_object = it->object;;
23787 enum display_element_type saved_what = it->what;
23788
23789 it->what = IT_CHARACTER;
23790 clear_position (it);
23791 it->object = Qnil;
23792 it->c = it->char_to_display = ' ';
23793 it->len = 1;
23794
23795 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23796 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23797 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23798 && !it->glyph_row->mode_line_p
23799 && face->background != FRAME_BACKGROUND_PIXEL (f))
23800 {
23801 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23802 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23803
23804 for (it->current_x = 0; g < e; g++)
23805 it->current_x += g->pixel_width;
23806
23807 it->area = LEFT_MARGIN_AREA;
23808 it->face_id = default_face->id;
23809 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23810 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23811 && g < it->glyph_row->glyphs[TEXT_AREA])
23812 {
23813 PRODUCE_GLYPHS (it);
23814
23815
23816 it->current_x += it->pixel_width;
23817 g++;
23818 }
23819
23820 it->current_x = saved_x;
23821 it->area = TEXT_AREA;
23822 }
23823
23824
23825
23826
23827 it->face_id = (it->glyph_row->ends_at_zv_p ?
23828 default_face->id : face->id);
23829
23830
23831
23832
23833
23834 it->current_x = it->glyph_row->used[TEXT_AREA];
23835
23836
23837
23838
23839
23840
23841
23842
23843 const int indicator_column =
23844 fill_column_indicator_column (it, 1) - it->first_visible_x;
23845
23846
23847 while (it->current_x <= it->last_visible_x)
23848 {
23849 if (it->current_x != indicator_column)
23850 PRODUCE_GLYPHS (it);
23851 else
23852 {
23853 int saved_face_id = it->face_id;
23854 it->face_id
23855 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23856 it->c = it->char_to_display
23857 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23858
23859 PRODUCE_GLYPHS (it);
23860
23861 it->face_id = saved_face_id;
23862 it->c = it->char_to_display = ' ';
23863 }
23864 }
23865
23866 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23867 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23868 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23869 && !it->glyph_row->mode_line_p
23870 && face->background != FRAME_BACKGROUND_PIXEL (f))
23871 {
23872 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23873 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23874
23875 for ( ; g < e; g++)
23876 it->current_x += g->pixel_width;
23877
23878 it->area = RIGHT_MARGIN_AREA;
23879 it->face_id = default_face->id;
23880 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23881 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23882 && g < it->glyph_row->glyphs[LAST_AREA])
23883 {
23884 PRODUCE_GLYPHS (it);
23885 it->current_x += it->pixel_width;
23886 g++;
23887 }
23888
23889 it->area = TEXT_AREA;
23890 }
23891
23892
23893
23894 it->current_x = saved_x;
23895 it->object = saved_object;
23896 it->position = saved_pos;
23897 it->what = saved_what;
23898 it->face_id = orig_face_id;
23899 }
23900 }
23901
23902
23903
23904
23905
23906 static bool
23907 trailing_whitespace_p (ptrdiff_t charpos)
23908 {
23909 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23910 int c = 0;
23911
23912 while (bytepos < ZV_BYTE
23913 && (c = FETCH_BYTE (bytepos),
23914 c == ' ' || c == '\t'))
23915 ++bytepos;
23916
23917 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23918 {
23919 if (bytepos != PT_BYTE)
23920 return true;
23921 }
23922 return false;
23923 }
23924
23925
23926
23927
23928 static void
23929 highlight_trailing_whitespace (struct it *it)
23930 {
23931 struct glyph_row *row = it->glyph_row;
23932 int used = row->used[TEXT_AREA];
23933
23934 if (used)
23935 {
23936 struct glyph *start = row->glyphs[TEXT_AREA];
23937 struct glyph *glyph = start + used - 1;
23938
23939 if (row->reversed_p)
23940 {
23941
23942
23943 glyph = start;
23944 start = row->glyphs[TEXT_AREA] + used - 1;
23945 }
23946
23947
23948
23949
23950
23951 if (!row->reversed_p)
23952 {
23953 while (glyph >= start
23954 && (glyph->type == CHAR_GLYPH
23955 || glyph->type == STRETCH_GLYPH)
23956 && NILP (glyph->object))
23957 --glyph;
23958 }
23959 else
23960 {
23961 while (glyph <= start
23962 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
23963 && NILP (glyph->object))
23964 ++glyph;
23965 }
23966
23967
23968
23969
23970 if ((row->reversed_p ? glyph <= start : glyph >= start)
23971 && BUFFERP (glyph->object)
23972 && (glyph->type == STRETCH_GLYPH
23973 || (glyph->type == CHAR_GLYPH
23974 && glyph->u.ch == ' '))
23975 && trailing_whitespace_p (glyph->charpos))
23976 {
23977 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
23978 if (face_id < 0)
23979 return;
23980
23981 if (!row->reversed_p)
23982 {
23983 while (glyph >= start
23984 && BUFFERP (glyph->object)
23985 && (glyph->type == STRETCH_GLYPH
23986 || (glyph->type == CHAR_GLYPH
23987 && glyph->u.ch == ' ')))
23988 (glyph--)->face_id = face_id;
23989 }
23990 else
23991 {
23992 while (glyph <= start
23993 && BUFFERP (glyph->object)
23994 && (glyph->type == STRETCH_GLYPH
23995 || (glyph->type == CHAR_GLYPH
23996 && glyph->u.ch == ' ')))
23997 (glyph++)->face_id = face_id;
23998 }
23999 }
24000 }
24001 }
24002
24003
24004
24005
24006
24007 static bool
24008 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
24009 {
24010 bool result = true;
24011
24012 if (charpos == CHARPOS (row->end.pos)
24013 || charpos == MATRIX_ROW_END_CHARPOS (row))
24014 {
24015
24016
24017
24018
24019
24020
24021
24022
24023 if (CHARPOS (row->end.string_pos) >= 0)
24024 {
24025 if (row->continued_p)
24026 result = true;
24027 else
24028 {
24029
24030 struct glyph *beg = row->glyphs[TEXT_AREA];
24031 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
24032 struct glyph *glyph;
24033
24034 result = false;
24035 for (glyph = end; glyph >= beg; --glyph)
24036 if (STRINGP (glyph->object))
24037 {
24038 Lisp_Object prop
24039 = Fget_char_property (make_fixnum (charpos),
24040 Qdisplay, Qnil);
24041 result =
24042 (!NILP (prop)
24043 && display_prop_string_p (prop, glyph->object));
24044
24045
24046
24047 if (!result)
24048 {
24049 Lisp_Object s = glyph->object;
24050
24051 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
24052 {
24053 ptrdiff_t gpos = glyph->charpos;
24054
24055 if (!NILP (Fget_char_property (make_fixnum (gpos),
24056 Qcursor, s)))
24057 {
24058 result = true;
24059 break;
24060 }
24061 }
24062 }
24063 break;
24064 }
24065 }
24066 }
24067 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
24068 {
24069
24070
24071
24072
24073 if (!row->ends_in_ellipsis_p)
24074 result = row->continued_p;
24075 else
24076
24077
24078
24079
24080 result = false;
24081 }
24082
24083
24084 else
24085 result = row->ends_at_zv_p;
24086 }
24087
24088 return result;
24089 }
24090
24091
24092
24093
24094 static bool
24095 cursor_row_p (struct glyph_row *row)
24096 {
24097 return row_for_charpos_p (row, PT);
24098 }
24099
24100
24101
24102
24103
24104
24105
24106
24107 static bool
24108 push_prefix_prop (struct it *it, Lisp_Object prop)
24109 {
24110 struct text_pos pos =
24111 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
24112
24113 eassert (it->method == GET_FROM_BUFFER
24114 || it->method == GET_FROM_DISPLAY_VECTOR
24115 || it->method == GET_FROM_STRING
24116 || it->method == GET_FROM_IMAGE);
24117
24118
24119
24120
24121
24122 push_it (it, &pos);
24123
24124 if (STRINGP (prop))
24125 {
24126 if (SCHARS (prop) == 0)
24127 {
24128 pop_it (it);
24129 return false;
24130 }
24131
24132 it->string = prop;
24133 it->string_from_prefix_prop_p = true;
24134 it->multibyte_p = STRING_MULTIBYTE (it->string);
24135 it->current.overlay_string_index = -1;
24136 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
24137 it->end_charpos = it->string_nchars = SCHARS (it->string);
24138 it->method = GET_FROM_STRING;
24139 it->stop_charpos = 0;
24140 it->prev_stop = 0;
24141 it->base_level_stop = 0;
24142 it->cmp_it.id = -1;
24143
24144
24145
24146 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
24147 it->paragraph_embedding = it->bidi_it.paragraph_dir;
24148 else
24149 it->paragraph_embedding = L2R;
24150
24151
24152 if (it->bidi_p)
24153 {
24154 it->bidi_it.string.lstring = it->string;
24155 it->bidi_it.string.s = NULL;
24156 it->bidi_it.string.schars = it->end_charpos;
24157 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
24158 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
24159 it->bidi_it.string.unibyte = !it->multibyte_p;
24160 it->bidi_it.w = it->w;
24161 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
24162 }
24163 }
24164 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
24165 {
24166 it->method = GET_FROM_STRETCH;
24167 it->object = prop;
24168 }
24169 #ifdef HAVE_WINDOW_SYSTEM
24170 else if (IMAGEP (prop))
24171 {
24172 it->what = IT_IMAGE;
24173 it->image_id = lookup_image (it->f, prop, it->face_id);
24174 it->method = GET_FROM_IMAGE;
24175 }
24176 #endif
24177 else
24178 {
24179 pop_it (it);
24180 return false;
24181 }
24182
24183 return true;
24184 }
24185
24186
24187
24188 static Lisp_Object
24189 get_it_property (struct it *it, Lisp_Object prop)
24190 {
24191 Lisp_Object position, object = it->object;
24192
24193 if (STRINGP (object))
24194 position = make_fixnum (IT_STRING_CHARPOS (*it));
24195 else if (BUFFERP (object))
24196 {
24197 position = make_fixnum (IT_CHARPOS (*it));
24198 object = it->window;
24199 }
24200 else
24201 return Qnil;
24202
24203 return Fget_char_property (position, prop, object);
24204 }
24205
24206
24207
24208
24209 static Lisp_Object
24210 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24211 {
24212 Lisp_Object prefix = get_it_property (it, prop);
24213
24214
24215
24216 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24217 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24218 it->w->contents);
24219 return prefix;
24220 }
24221
24222
24223
24224 static void
24225 handle_line_prefix (struct it *it)
24226 {
24227 Lisp_Object prefix;
24228
24229 if (it->continuation_lines_width > 0)
24230 {
24231 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24232 if (NILP (prefix))
24233 prefix = Vwrap_prefix;
24234 }
24235 else
24236 {
24237 prefix = get_line_prefix_it_property (it, Qline_prefix);
24238 if (NILP (prefix))
24239 prefix = Vline_prefix;
24240 }
24241 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24242 {
24243
24244
24245
24246 it->line_wrap = TRUNCATE;
24247 it->avoid_cursor_p = true;
24248 }
24249 }
24250
24251
24252
24253
24254
24255
24256
24257 static void
24258 unproduce_glyphs (struct it *it, int n)
24259 {
24260 struct glyph *glyph, *end;
24261
24262 eassert (it->glyph_row);
24263 eassert (it->glyph_row->reversed_p);
24264 eassert (it->area == TEXT_AREA);
24265 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24266
24267 if (n > it->glyph_row->used[TEXT_AREA])
24268 n = it->glyph_row->used[TEXT_AREA];
24269 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24270 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24271 for ( ; glyph < end; glyph++)
24272 glyph[-n] = *glyph;
24273 }
24274
24275
24276
24277 static void
24278 find_row_edges (struct it *it, struct glyph_row *row,
24279 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24280 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24281 {
24282
24283
24284
24285
24286
24287 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24288 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24289 else
24290
24291
24292
24293 row->minpos = row->start.pos;
24294 if (max_pos <= 0)
24295 {
24296 max_pos = CHARPOS (it->current.pos);
24297 max_bpos = BYTEPOS (it->current.pos);
24298 }
24299
24300
24301
24302
24303
24304
24305
24306
24307
24308
24309
24310
24311
24312
24313
24314
24315
24316 if (row->ends_at_zv_p)
24317 row->maxpos = it->current.pos;
24318 else if (row->used[TEXT_AREA])
24319 {
24320 bool seen_this_string = false;
24321 struct glyph_row *r1 = row - 1;
24322
24323
24324 if (STRINGP (it->object)
24325
24326 && row > it->w->desired_matrix->rows
24327
24328 && !r1->mode_line_p
24329
24330 && r1->ends_in_newline_from_string_p)
24331 {
24332 struct glyph *start, *end;
24333
24334
24335
24336
24337
24338 if (!r1->reversed_p)
24339 {
24340 start = r1->glyphs[TEXT_AREA];
24341 end = start + r1->used[TEXT_AREA];
24342
24343 while (end > start
24344 && NILP ((end - 1)->object)
24345 && (end - 1)->charpos <= 0)
24346 --end;
24347 if (end > start)
24348 {
24349 if (EQ ((end - 1)->object, it->object))
24350 seen_this_string = true;
24351 }
24352 else
24353
24354
24355
24356
24357
24358 seen_this_string = true;
24359 }
24360 else
24361 {
24362 end = r1->glyphs[TEXT_AREA] - 1;
24363 start = end + r1->used[TEXT_AREA];
24364 while (end < start
24365 && NILP ((end + 1)->object)
24366 && (end + 1)->charpos <= 0)
24367 ++end;
24368 if (end < start)
24369 {
24370 if (EQ ((end + 1)->object, it->object))
24371 seen_this_string = true;
24372 }
24373 else
24374 seen_this_string = true;
24375 }
24376 }
24377
24378
24379
24380 if (row->ends_in_newline_from_string_p && !seen_this_string)
24381 {
24382
24383
24384
24385
24386
24387
24388
24389
24390 if (CHARPOS (row->end.pos) > max_pos)
24391 inc_both (&max_pos, &max_bpos);
24392 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24393 }
24394 else if (CHARPOS (it->eol_pos) > 0)
24395 SET_TEXT_POS (row->maxpos,
24396 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24397 else if (row->continued_p)
24398 {
24399
24400
24401
24402
24403
24404
24405 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24406 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24407 else
24408 {
24409 inc_both (&max_pos, &max_bpos);
24410 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24411 }
24412 }
24413 else if (row->truncated_on_right_p)
24414
24415
24416
24417 row->maxpos = it->current.pos;
24418 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24419
24420 row->maxpos = row->minpos;
24421 else
24422 emacs_abort ();
24423 }
24424 else
24425 row->maxpos = it->current.pos;
24426 }
24427
24428
24429
24430 static ptrdiff_t
24431 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24432 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24433 {
24434 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24435 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24436
24437 ptrdiff_t val;
24438 specpdl_ref pdl_count = SPECPDL_INDEX ();
24439 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24440 labeled_restrictions_remove_in_current_buffer ();
24441 Fwiden ();
24442 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24443 unbind_to (pdl_count, Qnil);
24444 return val;
24445 }
24446
24447
24448
24449 static ptrdiff_t
24450 display_count_lines_visually (struct it *it)
24451 {
24452 struct it tem_it;
24453 ptrdiff_t to;
24454 struct text_pos from;
24455
24456
24457
24458
24459
24460
24461 if (it->lnum_bytepos > 0)
24462 return it->lnum + 1;
24463 else
24464 {
24465 specpdl_ref count = SPECPDL_INDEX ();
24466
24467 if (IT_CHARPOS (*it) <= PT)
24468 {
24469 from = it->current.pos;
24470 to = PT;
24471 }
24472 else
24473 {
24474 SET_TEXT_POS (from, PT, PT_BYTE);
24475 to = IT_CHARPOS (*it);
24476 }
24477
24478
24479
24480 specbind (Qdisplay_line_numbers, Qrelative);
24481 start_display (&tem_it, it->w, from);
24482
24483
24484
24485
24486 move_it_to (&tem_it, to, -1,
24487 tem_it.last_visible_y
24488 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24489 -1, MOVE_TO_POS | MOVE_TO_Y);
24490 unbind_to (count, Qnil);
24491 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24492 }
24493 }
24494
24495
24496
24497
24498 static void
24499 maybe_produce_line_number (struct it *it)
24500 {
24501 ptrdiff_t last_line = it->lnum;
24502 ptrdiff_t start_from, bytepos;
24503 ptrdiff_t this_line;
24504 bool first_time = false;
24505 ptrdiff_t beg_byte;
24506 ptrdiff_t z_byte;
24507 bool line_numbers_wide;
24508 void *itdata = bidi_shelve_cache ();
24509
24510 if (display_line_numbers_offset
24511 && !display_line_numbers_widen
24512 && !EQ (Vdisplay_line_numbers, Qvisual)
24513 && !EQ (Vdisplay_line_numbers, Qrelative))
24514 line_numbers_wide = true;
24515 else
24516 line_numbers_wide = display_line_numbers_widen;
24517
24518 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24519 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24520
24521 if (EQ (Vdisplay_line_numbers, Qvisual))
24522 this_line = display_count_lines_visually (it);
24523 else
24524 {
24525 if (!last_line)
24526 {
24527
24528 if (it->w->base_line_number > 0
24529 && it->w->base_line_pos > 0
24530 && it->w->base_line_pos <= IT_CHARPOS (*it)
24531
24532
24533
24534
24535 && !(line_numbers_wide
24536 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24537 && !current_buffer->clip_changed)
24538 {
24539 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24540 last_line = it->w->base_line_number - 1;
24541 }
24542 else
24543 start_from = beg_byte;
24544 if (!it->lnum_bytepos)
24545 first_time = true;
24546 }
24547 else
24548 start_from = it->lnum_bytepos;
24549
24550
24551
24552
24553 if (!(beg_byte <= start_from && start_from <= z_byte))
24554 {
24555 last_line = 0;
24556 start_from = beg_byte;
24557 }
24558
24559 this_line =
24560 last_line + display_count_lines_logically (start_from,
24561 IT_BYTEPOS (*it),
24562 IT_CHARPOS (*it), &bytepos);
24563 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24564 eassert (bytepos == IT_BYTEPOS (*it));
24565 }
24566
24567
24568 if (this_line != last_line || !it->lnum_bytepos)
24569 {
24570 it->lnum = this_line;
24571 it->lnum_bytepos = IT_BYTEPOS (*it);
24572 }
24573
24574
24575 struct it tem_it;
24576 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24577 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24578 ptrdiff_t lnum_offset = -1;
24579 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24580 int current_lnum_face_id
24581 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24582
24583
24584 bool save_free_realized_faces = inhibit_free_realized_faces;
24585 inhibit_free_realized_faces = true;
24586
24587 if ((EQ (Vdisplay_line_numbers, Qrelative)
24588 || EQ (Vdisplay_line_numbers, Qvisual)
24589 || lnum_face_id != current_lnum_face_id)
24590 && !it->pt_lnum)
24591 {
24592 ptrdiff_t ignored;
24593 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24594 it->pt_lnum =
24595 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24596 PT, &ignored);
24597 else
24598 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24599 &ignored);
24600 }
24601
24602 if (!it->lnum_width)
24603 {
24604 if (FIXNATP (Vdisplay_line_numbers_width))
24605 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24606
24607
24608
24609 ptrdiff_t max_lnum;
24610
24611 if (NILP (Vdisplay_line_numbers_current_absolute)
24612 && (EQ (Vdisplay_line_numbers, Qrelative)
24613 || EQ (Vdisplay_line_numbers, Qvisual)))
24614
24615
24616 max_lnum = it->w->desired_matrix->nrows - 2;
24617 else if (EQ (Vdisplay_line_numbers, Qvisual))
24618 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24619 else
24620 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24621 max_lnum = max (1, max_lnum);
24622 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24623 eassert (it->lnum_width > 0);
24624 }
24625 if (EQ (Vdisplay_line_numbers, Qrelative))
24626 lnum_offset = it->pt_lnum;
24627 else if (EQ (Vdisplay_line_numbers, Qvisual))
24628 lnum_offset = 0;
24629 else if (display_line_numbers_offset)
24630 lnum_offset -= display_line_numbers_offset;
24631
24632
24633
24634 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24635 if ((EQ (Vdisplay_line_numbers, Qrelative)
24636 || EQ (Vdisplay_line_numbers, Qvisual))
24637 && lnum_to_display == 0
24638 && !NILP (Vdisplay_line_numbers_current_absolute))
24639 lnum_to_display = it->pt_lnum + 1;
24640
24641
24642
24643
24644
24645 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24646 strcat (lnum_buf, " ");
24647
24648
24649 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24650
24651 DEFAULT_FACE_ID);
24652 scratch_glyph_row.reversed_p = false;
24653 scratch_glyph_row.used[TEXT_AREA] = 0;
24654 SET_TEXT_POS (tem_it.position, 0, 0);
24655 tem_it.avoid_cursor_p = true;
24656 tem_it.bidi_p = true;
24657 tem_it.bidi_it.type = WEAK_EN;
24658
24659
24660
24661 tem_it.bidi_it.resolved_level = 2;
24662
24663
24664
24665 int width_limit =
24666 tem_it.last_visible_x - tem_it.first_visible_x
24667 - 3 * FRAME_COLUMN_WIDTH (it->f);
24668
24669 tem_it.face_id = lnum_face_id;
24670
24671
24672 if (lnum_face_id != current_lnum_face_id
24673 && (EQ (Vdisplay_line_numbers, Qvisual)
24674 ? this_line == 0
24675 : this_line == it->pt_lnum)
24676 && it->what != IT_EOB)
24677 tem_it.face_id = current_lnum_face_id;
24678 else if (!beyond_zv)
24679 {
24680 if (display_line_numbers_major_tick > 0
24681 && (lnum_to_display % display_line_numbers_major_tick == 0))
24682 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24683 0, DEFAULT_FACE_ID);
24684 else if (display_line_numbers_minor_tick > 0
24685 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24686 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24687 0, DEFAULT_FACE_ID);
24688 }
24689
24690
24691 for (const char *p = lnum_buf; *p; p++)
24692 {
24693
24694
24695 if (beyond_zv
24696
24697 || (!EQ (Vdisplay_line_numbers, Qvisual)
24698 && (it->continuation_lines_width > 0
24699 || (this_line == last_line && !first_time))))
24700 tem_it.c = tem_it.char_to_display = ' ';
24701 else
24702 tem_it.c = tem_it.char_to_display = *p;
24703 tem_it.len = 1;
24704
24705 SET_TEXT_POS (tem_it.position, -1, -1);
24706 PRODUCE_GLYPHS (&tem_it);
24707
24708
24709
24710 if (tem_it.current_x >= width_limit)
24711 {
24712 it->lnum_width = 0;
24713 it->lnum_pixel_width = 0;
24714 bidi_unshelve_cache (itdata, false);
24715 inhibit_free_realized_faces = save_free_realized_faces;
24716 return;
24717 }
24718 }
24719
24720 inhibit_free_realized_faces = save_free_realized_faces;
24721
24722
24723 it->lnum_pixel_width = tem_it.current_x;
24724
24725 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24726 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24727 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24728 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24729
24730 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24731
24732 for ( ; g < e; g++)
24733 {
24734 it->current_x += g->pixel_width;
24735
24736
24737
24738 if (it->current_x > it->first_visible_x)
24739 it->hpos++;
24740 if (p)
24741 {
24742 *p++ = *g;
24743 (*u)++;
24744 }
24745 }
24746
24747
24748
24749
24750 if (!beyond_zv)
24751 {
24752 if (it->glyph_row)
24753 {
24754 struct glyph_row *row = it->glyph_row;
24755
24756 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24757 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24758 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24759 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24760 tem_it.max_phys_descent);
24761 }
24762 else
24763 {
24764 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24765 it->max_descent = max (it->max_descent, tem_it.max_descent);
24766 it->max_phys_ascent = max (it->max_phys_ascent,
24767 tem_it.max_phys_ascent);
24768 it->max_phys_descent = max (it->max_phys_descent,
24769 tem_it.max_phys_descent);
24770 }
24771 }
24772
24773 it->line_number_produced_p = true;
24774
24775 bidi_unshelve_cache (itdata, false);
24776 }
24777
24778
24779
24780 static bool
24781 should_produce_line_number (struct it *it)
24782 {
24783 if (NILP (Vdisplay_line_numbers))
24784 return false;
24785
24786
24787 if (MINI_WINDOW_P (it->w))
24788 return false;
24789
24790 #ifdef HAVE_WINDOW_SYSTEM
24791
24792 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24793 return false;
24794 #endif
24795
24796
24797
24798
24799
24800 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24801 Qdisplay_line_numbers_disable,
24802 it->window);
24803
24804
24805
24806 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24807 val = disable_line_numbers_overlay_at_eob ();
24808 return NILP (val) ? true : false;
24809 }
24810
24811
24812
24813
24814
24815 static bool
24816 row_text_area_empty (struct glyph_row *row)
24817 {
24818 if (!row->reversed_p)
24819 {
24820 for (struct glyph *g = row->glyphs[TEXT_AREA];
24821 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24822 g++)
24823 if (!NILP (g->object) || g->charpos > 0)
24824 return false;
24825 }
24826 else
24827 {
24828 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24829 g > row->glyphs[TEXT_AREA];
24830 g--)
24831 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24832 return false;
24833 }
24834
24835 return true;
24836 }
24837
24838
24839
24840
24841
24842
24843
24844
24845 static bool
24846 display_line (struct it *it, int cursor_vpos)
24847 {
24848 struct glyph_row *row = it->glyph_row;
24849 Lisp_Object overlay_arrow_string;
24850 struct it wrap_it;
24851 void *wrap_data = NULL;
24852 bool may_wrap = false;
24853 int wrap_x UNINIT;
24854 int wrap_row_used = -1;
24855 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24856 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24857 int wrap_row_extra_line_spacing UNINIT;
24858 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24859 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24860 int cvpos;
24861 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24862 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24863 bool pending_handle_line_prefix = false;
24864 int tab_line = window_wants_tab_line (it->w);
24865 int header_line = window_wants_header_line (it->w);
24866 bool hscroll_this_line = (cursor_vpos >= 0
24867 && it->vpos == cursor_vpos - tab_line - header_line
24868 && hscrolling_current_line_p (it->w));
24869 int first_visible_x = it->first_visible_x;
24870 int last_visible_x = it->last_visible_x;
24871 int x_incr = 0;
24872
24873
24874 eassert (it->hpos == 0 && it->current_x == 0);
24875
24876 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24877 >= it->w->desired_matrix->nrows)
24878 {
24879 it->w->nrows_scale_factor++;
24880 it->f->fonts_changed = true;
24881 return false;
24882 }
24883
24884
24885 prepare_desired_row (it->w, row, false);
24886
24887 row->y = it->current_y;
24888 row->start = it->start;
24889 row->continuation_lines_width = it->continuation_lines_width;
24890 row->displays_text_p = true;
24891 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24892 it->starts_in_middle_of_char_p = false;
24893 it->stretch_adjust = 0;
24894 it->line_number_produced_p = false;
24895
24896
24897
24898
24899 if (hscroll_this_line)
24900 x_incr =
24901 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24902 * FRAME_COLUMN_WIDTH (it->f);
24903
24904 bool line_number_needed = should_produce_line_number (it);
24905
24906
24907
24908
24909 if (it->current_x < it->first_visible_x + x_incr)
24910 {
24911 enum move_it_result move_result;
24912
24913 this_line_min_pos = row->start.pos;
24914 if (hscroll_this_line)
24915 {
24916 it->first_visible_x += x_incr;
24917 it->last_visible_x += x_incr;
24918 }
24919 if (current_buffer->long_line_optimizations_p
24920 && it->line_wrap == TRUNCATE
24921 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24922 {
24923
24924
24925
24926
24927 ptrdiff_t chars_to_skip =
24928 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24929 move_result = fast_move_it_horizontally (it, chars_to_skip);
24930
24931 if (move_result == MOVE_X_REACHED)
24932 it->current_x = it->first_visible_x;
24933 else
24934 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24935 }
24936 else
24937 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
24938 MOVE_TO_POS | MOVE_TO_X);
24939
24940
24941
24942
24943
24944
24945 if (it->current_x < it->first_visible_x
24946 && (move_result == MOVE_NEWLINE_OR_CR
24947 || move_result == MOVE_POS_MATCH_OR_ZV))
24948 it->current_x = it->first_visible_x;
24949
24950
24951
24952 it->line_number_produced_p = false;
24953
24954
24955
24956
24957
24958
24959
24960
24961 min_pos = CHARPOS (this_line_min_pos);
24962 min_bpos = BYTEPOS (this_line_min_pos);
24963
24964
24965 if (line_number_needed)
24966 maybe_produce_line_number (it);
24967 }
24968 else if (it->area == TEXT_AREA)
24969 {
24970
24971 if (line_number_needed)
24972 maybe_produce_line_number (it);
24973
24974
24975
24976 handle_line_prefix (it);
24977 }
24978 else
24979 {
24980
24981
24982
24983
24984
24985
24986
24987 pending_handle_line_prefix = true;
24988 }
24989
24990
24991
24992 row->ascent = it->max_ascent;
24993 row->height = it->max_ascent + it->max_descent;
24994 row->phys_ascent = it->max_phys_ascent;
24995 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
24996 row->extra_line_spacing = it->max_extra_line_spacing;
24997
24998
24999 #define RECORD_MAX_MIN_POS(IT) \
25000 do \
25001 { \
25002 bool composition_p \
25003 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
25004 ptrdiff_t current_pos = \
25005 composition_p ? (IT)->cmp_it.charpos \
25006 : IT_CHARPOS (*(IT)); \
25007 ptrdiff_t current_bpos = \
25008 composition_p ? CHAR_TO_BYTE (current_pos) \
25009 : IT_BYTEPOS (*(IT)); \
25010 if (current_pos < min_pos) \
25011 { \
25012 min_pos = current_pos; \
25013 min_bpos = current_bpos; \
25014 } \
25015 if (IT_CHARPOS (*it) > max_pos) \
25016 { \
25017 max_pos = IT_CHARPOS (*it); \
25018 max_bpos = IT_BYTEPOS (*it); \
25019 } \
25020 } \
25021 while (false)
25022
25023
25024
25025 while (true)
25026 {
25027 int n_glyphs_before, hpos_before, x_before;
25028 int x, nglyphs;
25029 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
25030
25031
25032
25033 if (!get_next_display_element (it))
25034 {
25035 bool row_has_glyphs = false;
25036
25037
25038
25039
25040 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25041 row->exact_window_width_line_p = true;
25042 else if ((append_space_for_newline (it, true)
25043 && row->used[TEXT_AREA] == 1)
25044 || row->used[TEXT_AREA] == 0
25045 || (row_has_glyphs = row_text_area_empty (row)))
25046 {
25047 row->glyphs[TEXT_AREA]->charpos = -1;
25048
25049
25050 if (!row_has_glyphs)
25051 row->displays_text_p = false;
25052
25053 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
25054 && (!MINI_WINDOW_P (it->w)))
25055 row->indicate_empty_line_p = true;
25056 }
25057
25058 it->continuation_lines_width = 0;
25059
25060
25061
25062
25063 it->font_height = Qnil;
25064 it->voffset = 0;
25065 row->ends_at_zv_p = true;
25066
25067
25068
25069
25070
25071
25072
25073
25074 if (row->reversed_p
25075 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
25076 != DEFAULT_FACE_ID)
25077 extend_face_to_end_of_line (it);
25078 break;
25079 }
25080
25081
25082
25083 n_glyphs_before = row->used[TEXT_AREA];
25084 x = it->current_x;
25085
25086
25087
25088 if (it->line_wrap != TRUNCATE)
25089 {
25090 ascent = it->max_ascent;
25091 descent = it->max_descent;
25092 phys_ascent = it->max_phys_ascent;
25093 phys_descent = it->max_phys_descent;
25094
25095 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
25096 {
25097 bool next_may_wrap = may_wrap;
25098
25099 if (char_can_wrap_after (it))
25100 next_may_wrap = true;
25101 else
25102 next_may_wrap = false;
25103
25104 if (may_wrap && char_can_wrap_before (it))
25105 {
25106 SAVE_IT (wrap_it, *it, wrap_data);
25107 wrap_x = x;
25108 wrap_row_used = row->used[TEXT_AREA];
25109 wrap_row_ascent = row->ascent;
25110 wrap_row_height = row->height;
25111 wrap_row_phys_ascent = row->phys_ascent;
25112 wrap_row_phys_height = row->phys_height;
25113 wrap_row_extra_line_spacing = row->extra_line_spacing;
25114 wrap_row_min_pos = min_pos;
25115 wrap_row_min_bpos = min_bpos;
25116 wrap_row_max_pos = max_pos;
25117 wrap_row_max_bpos = max_bpos;
25118 }
25119
25120 may_wrap = next_may_wrap;
25121 }
25122 }
25123
25124 PRODUCE_GLYPHS (it);
25125
25126
25127
25128 if (it->area != TEXT_AREA)
25129 {
25130 row->ascent = max (row->ascent, it->max_ascent);
25131 row->height = max (row->height, it->max_ascent + it->max_descent);
25132 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25133 row->phys_height = max (row->phys_height,
25134 it->max_phys_ascent + it->max_phys_descent);
25135 row->extra_line_spacing = max (row->extra_line_spacing,
25136 it->max_extra_line_spacing);
25137 set_iterator_to_next (it, true);
25138
25139
25140
25141 if (it->area == TEXT_AREA && pending_handle_line_prefix)
25142 {
25143
25144 if (line_number_needed)
25145 maybe_produce_line_number (it);
25146
25147 pending_handle_line_prefix = false;
25148 handle_line_prefix (it);
25149 }
25150 continue;
25151 }
25152
25153
25154
25155
25156
25157
25158
25159
25160
25161
25162 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
25163 hpos_before = it->hpos;
25164 x_before = x;
25165
25166 if (
25167 nglyphs > 0
25168
25169 && it->current_x < it->last_visible_x)
25170 {
25171 it->hpos += nglyphs;
25172 row->ascent = max (row->ascent, it->max_ascent);
25173 row->height = max (row->height, it->max_ascent + it->max_descent);
25174 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25175 row->phys_height = max (row->phys_height,
25176 it->max_phys_ascent + it->max_phys_descent);
25177 row->extra_line_spacing = max (row->extra_line_spacing,
25178 it->max_extra_line_spacing);
25179 if (it->current_x - it->pixel_width < it->first_visible_x
25180
25181
25182
25183 && !line_number_needed
25184
25185
25186
25187
25188 && !row->reversed_p)
25189 row->x = x - it->first_visible_x;
25190
25191
25192 if (it->bidi_p)
25193 RECORD_MAX_MIN_POS (it);
25194 }
25195 else
25196 {
25197 int i, new_x;
25198 struct glyph *glyph;
25199
25200 for (i = 0; i < nglyphs; ++i, x = new_x)
25201 {
25202
25203
25204
25205 if (!row->reversed_p)
25206 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25207 else
25208 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25209 new_x = x + glyph->pixel_width;
25210
25211 if (
25212 it->line_wrap != TRUNCATE
25213 && (
25214 new_x > it->last_visible_x
25215
25216 || (new_x == it->last_visible_x
25217 && FRAME_WINDOW_P (it->f)
25218 && (row->reversed_p
25219 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25220 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25221 {
25222
25223
25224 if (it->hpos == 0
25225 || (new_x == it->last_visible_x
25226 && FRAME_WINDOW_P (it->f)
25227 && (row->reversed_p
25228 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25229 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25230 {
25231
25232
25233
25234
25235 row->continued_p = true;
25236 it->current_x = new_x;
25237 it->continuation_lines_width += new_x;
25238 ++it->hpos;
25239 if (i == nglyphs - 1)
25240 {
25241
25242
25243 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25244 && wrap_row_used > 0
25245
25246
25247
25248
25249
25250
25251
25252
25253
25254
25255 && (!may_wrap || !char_can_wrap_before (it)))
25256 goto back_to_wrap;
25257
25258
25259
25260
25261 if (it->bidi_p)
25262 RECORD_MAX_MIN_POS (it);
25263 set_iterator_to_next (it, true);
25264 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25265 {
25266 if (!get_next_display_element (it))
25267 {
25268 row->exact_window_width_line_p = true;
25269 it->continuation_lines_width = 0;
25270 it->font_height = Qnil;
25271 it->voffset = 0;
25272 row->continued_p = false;
25273 row->ends_at_zv_p = true;
25274 }
25275 else if (ITERATOR_AT_END_OF_LINE_P (it))
25276 {
25277 row->continued_p = false;
25278 row->exact_window_width_line_p = true;
25279 }
25280
25281
25282 else if (wrap_row_used > 0
25283
25284
25285
25286
25287
25288
25289
25290
25291
25292 && (!may_wrap || !char_can_wrap_before (it)))
25293 goto back_to_wrap;
25294
25295 }
25296 }
25297 else if (it->bidi_p)
25298 RECORD_MAX_MIN_POS (it);
25299 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25300 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25301 extend_face_to_end_of_line (it);
25302 }
25303 else if (CHAR_GLYPH_PADDING_P (*glyph)
25304 && !FRAME_WINDOW_P (it->f))
25305 {
25306
25307
25308
25309 if (row->reversed_p)
25310 unproduce_glyphs (it, row->used[TEXT_AREA]
25311 - n_glyphs_before);
25312 row->used[TEXT_AREA] = n_glyphs_before;
25313
25314
25315
25316 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25317 < row->glyphs[1 + TEXT_AREA])
25318 produce_special_glyphs (it, IT_CONTINUATION);
25319
25320 row->continued_p = true;
25321 it->current_x = x_before;
25322 it->continuation_lines_width += x_before;
25323
25324
25325
25326 it->max_ascent = ascent;
25327 it->max_descent = descent;
25328 it->max_phys_ascent = phys_ascent;
25329 it->max_phys_descent = phys_descent;
25330 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25331 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25332 extend_face_to_end_of_line (it);
25333 }
25334 else if (wrap_row_used > 0)
25335 {
25336 back_to_wrap:
25337 if (row->reversed_p)
25338 unproduce_glyphs (it,
25339 row->used[TEXT_AREA] - wrap_row_used);
25340 RESTORE_IT (it, &wrap_it, wrap_data);
25341 it->continuation_lines_width += wrap_x;
25342 row->used[TEXT_AREA] = wrap_row_used;
25343 row->ascent = wrap_row_ascent;
25344 row->height = wrap_row_height;
25345 row->phys_ascent = wrap_row_phys_ascent;
25346 row->phys_height = wrap_row_phys_height;
25347 row->extra_line_spacing = wrap_row_extra_line_spacing;
25348 min_pos = wrap_row_min_pos;
25349 min_bpos = wrap_row_min_bpos;
25350 max_pos = wrap_row_max_pos;
25351 max_bpos = wrap_row_max_bpos;
25352 row->continued_p = true;
25353 row->ends_at_zv_p = false;
25354 row->exact_window_width_line_p = false;
25355
25356
25357
25358 extend_face_to_end_of_line (it);
25359 }
25360 else if ((it->what == IT_CHARACTER
25361 || it->what == IT_STRETCH
25362 || it->what == IT_COMPOSITION)
25363 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25364 {
25365
25366
25367
25368
25369
25370 if ((row->reversed_p
25371 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25372 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25373 produce_special_glyphs (it, IT_CONTINUATION);
25374 it->continuation_lines_width += it->last_visible_x;
25375 row->ends_in_middle_of_char_p = true;
25376 row->continued_p = true;
25377 glyph->pixel_width = it->last_visible_x - x;
25378 it->starts_in_middle_of_char_p = true;
25379 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25380 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25381 extend_face_to_end_of_line (it);
25382 }
25383 else
25384 {
25385
25386
25387
25388 if (row->reversed_p)
25389 unproduce_glyphs (it, row->used[TEXT_AREA]
25390 - (n_glyphs_before + i));
25391 row->used[TEXT_AREA] = n_glyphs_before + i;
25392
25393
25394 it->current_x = x_before;
25395 it->continuation_lines_width += x;
25396 if (!FRAME_WINDOW_P (it->f)
25397 || (row->reversed_p
25398 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25399 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25400 produce_special_glyphs (it, IT_CONTINUATION);
25401 row->continued_p = true;
25402
25403 extend_face_to_end_of_line (it);
25404
25405 if (nglyphs > 1 && i > 0)
25406 {
25407 row->ends_in_middle_of_char_p = true;
25408 it->starts_in_middle_of_char_p = true;
25409 }
25410
25411
25412
25413 it->max_ascent = ascent;
25414 it->max_descent = descent;
25415 it->max_phys_ascent = phys_ascent;
25416 it->max_phys_descent = phys_descent;
25417 }
25418
25419 break;
25420 }
25421 else if (new_x > it->first_visible_x)
25422 {
25423
25424 ++it->hpos;
25425
25426
25427
25428
25429 if (it->bidi_p)
25430 RECORD_MAX_MIN_POS (it);
25431
25432 if (x < it->first_visible_x && !row->reversed_p
25433 && !line_number_needed)
25434
25435
25436
25437
25438
25439
25440 row->x = x - it->first_visible_x;
25441
25442
25443
25444
25445
25446
25447 if (row->reversed_p
25448 && new_x > it->last_visible_x
25449 && !line_number_needed
25450 && !(it->line_wrap == TRUNCATE
25451 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25452 {
25453 eassert (FRAME_WINDOW_P (it->f));
25454 row->x = it->last_visible_x - new_x;
25455 }
25456 }
25457 else
25458 {
25459
25460
25461
25462
25463
25464 eassert (it->first_visible_x <= it->last_visible_x);
25465 }
25466 }
25467
25468
25469 if (it->bidi_p && nglyphs == 0)
25470 RECORD_MAX_MIN_POS (it);
25471
25472 row->ascent = max (row->ascent, it->max_ascent);
25473 row->height = max (row->height, it->max_ascent + it->max_descent);
25474 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25475 row->phys_height = max (row->phys_height,
25476 it->max_phys_ascent + it->max_phys_descent);
25477 row->extra_line_spacing = max (row->extra_line_spacing,
25478 it->max_extra_line_spacing);
25479
25480
25481 if (row->continued_p || row->ends_at_zv_p)
25482 break;
25483 }
25484
25485 at_end_of_line:
25486
25487
25488
25489 if (ITERATOR_AT_END_OF_LINE_P (it))
25490 {
25491 int used_before = row->used[TEXT_AREA];
25492
25493 row->ends_in_newline_from_string_p = STRINGP (it->object);
25494
25495
25496
25497 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25498 append_space_for_newline (it, false);
25499
25500
25501 extend_face_to_end_of_line (it);
25502
25503
25504 if (used_before == 0)
25505 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25506
25507
25508
25509 it->eol_pos = it->current.pos;
25510
25511
25512 set_iterator_to_next (it, true);
25513 it->continuation_lines_width = 0;
25514 break;
25515 }
25516
25517
25518
25519
25520
25521
25522
25523
25524 bool overwide_wrap_prefix =
25525 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25526 && it->sp > 0 && it->method == GET_FROM_STRETCH
25527 && it->current_x >= it->last_visible_x
25528 && it->continuation_lines_width > 0
25529 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25530
25531
25532
25533 if (!overwide_wrap_prefix)
25534 set_iterator_to_next (it, true);
25535
25536
25537
25538 if (it->line_wrap == TRUNCATE
25539 && ((FRAME_WINDOW_P (it->f)
25540
25541
25542
25543
25544 && ((row->reversed_p
25545 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25546 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25547 || it->what == IT_IMAGE))
25548 ? (it->current_x >= it->last_visible_x)
25549 : (it->current_x > it->last_visible_x)))
25550 {
25551
25552 if (!FRAME_WINDOW_P (it->f)
25553 || (row->reversed_p
25554 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25555 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25556 {
25557 int i, n;
25558
25559 if (!row->reversed_p)
25560 {
25561 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25562 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25563 break;
25564 }
25565 else
25566 {
25567 for (i = 0; i < row->used[TEXT_AREA]; i++)
25568 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25569 break;
25570
25571
25572
25573
25574
25575 unproduce_glyphs (it, i + 1);
25576
25577 i = row->used[TEXT_AREA] - (i + 1);
25578 }
25579
25580
25581
25582
25583 if (it->current_x > it->last_visible_x)
25584 {
25585 it->current_x = x_before;
25586 if (!FRAME_WINDOW_P (it->f))
25587 {
25588 for (n = row->used[TEXT_AREA]; i < n; ++i)
25589 {
25590 row->used[TEXT_AREA] = i;
25591 produce_special_glyphs (it, IT_TRUNCATION);
25592 }
25593 }
25594 else
25595 {
25596 row->used[TEXT_AREA] = i;
25597 produce_special_glyphs (it, IT_TRUNCATION);
25598 }
25599 it->hpos = hpos_before;
25600 }
25601 }
25602 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25603 {
25604
25605 if (!get_next_display_element (it))
25606 {
25607 it->continuation_lines_width = 0;
25608 it->font_height = Qnil;
25609 it->voffset = 0;
25610 row->ends_at_zv_p = true;
25611 row->exact_window_width_line_p = true;
25612 break;
25613 }
25614 if (ITERATOR_AT_END_OF_LINE_P (it))
25615 {
25616 row->exact_window_width_line_p = true;
25617 goto at_end_of_line;
25618 }
25619 it->current_x = x_before;
25620 it->hpos = hpos_before;
25621 }
25622
25623 row->truncated_on_right_p = true;
25624 it->continuation_lines_width = 0;
25625 reseat_at_next_visible_line_start (it, false);
25626
25627
25628
25629
25630 if (IT_BYTEPOS (*it) > BEG_BYTE)
25631 row->ends_at_zv_p =
25632 IT_BYTEPOS (*it) >= ZV_BYTE
25633 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25634 else
25635 row->ends_at_zv_p = false;
25636 break;
25637 }
25638 }
25639
25640 if (wrap_data)
25641 bidi_unshelve_cache (wrap_data, true);
25642
25643
25644
25645 if (it->first_visible_x
25646 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25647 {
25648 if (!FRAME_WINDOW_P (it->f)
25649 || (((row->reversed_p
25650 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25651 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25652
25653
25654 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25655 insert_left_trunc_glyphs (it);
25656 row->truncated_on_left_p = true;
25657 }
25658
25659
25660
25661
25662
25663
25664 row->end = it->current;
25665 if (!it->bidi_p)
25666 {
25667 row->minpos = row->start.pos;
25668 row->maxpos = row->end.pos;
25669 }
25670 else
25671 {
25672
25673
25674
25675
25676 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25677 }
25678
25679
25680
25681
25682
25683 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25684 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25685 !NILP (overlay_arrow_string)))
25686 {
25687
25688 if (STRINGP (overlay_arrow_string))
25689 {
25690 struct glyph_row *arrow_row
25691 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25692 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25693 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25694 struct glyph *p = row->glyphs[TEXT_AREA];
25695 struct glyph *p2, *end;
25696
25697
25698 while (glyph < arrow_end)
25699 *p++ = *glyph++;
25700
25701
25702 p2 = p;
25703 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25704 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25705 ++p2;
25706 if (p2 > p)
25707 {
25708 while (p2 < end)
25709 *p++ = *p2++;
25710 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25711 }
25712 }
25713 else
25714 {
25715 eassert (FIXNUMP (overlay_arrow_string));
25716 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25717 }
25718 overlay_arrow_seen = true;
25719 }
25720
25721
25722 if (!NILP (Vshow_trailing_whitespace))
25723 highlight_trailing_whitespace (it);
25724
25725
25726 compute_line_metrics (it);
25727
25728
25729
25730
25731
25732
25733
25734 row->ends_in_ellipsis_p
25735 = (it->method == GET_FROM_DISPLAY_VECTOR
25736 && it->ellipsis_p);
25737
25738
25739 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25740 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25741 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25742 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25743
25744 it->left_user_fringe_bitmap = 0;
25745 it->left_user_fringe_face_id = 0;
25746 it->right_user_fringe_bitmap = 0;
25747 it->right_user_fringe_face_id = 0;
25748
25749
25750
25751
25752
25753
25754 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25755 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25756 row->redraw_fringe_bitmaps_p = true;
25757
25758
25759 cvpos = it->w->cursor.vpos;
25760 if ((cvpos < 0
25761
25762
25763
25764
25765
25766
25767
25768
25769 || (it->bidi_p
25770 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25771 && PT >= MATRIX_ROW_START_CHARPOS (row)
25772 && PT <= MATRIX_ROW_END_CHARPOS (row)
25773 && cursor_row_p (row))
25774 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25775
25776
25777
25778
25779
25780 it->current_x = it->hpos = 0;
25781 it->current_y += row->height;
25782
25783
25784 if (hscroll_this_line)
25785 {
25786 it->first_visible_x = first_visible_x;
25787 it->last_visible_x = last_visible_x;
25788 }
25789 SET_TEXT_POS (it->eol_pos, 0, 0);
25790 ++it->vpos;
25791 ++it->glyph_row;
25792
25793
25794
25795
25796 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25797 it->glyph_row->reversed_p = row->reversed_p;
25798 it->start = row->end;
25799 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25800
25801 #undef RECORD_MAX_MIN_POS
25802 }
25803
25804 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25805 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25806 doc:
25807
25808
25809
25810
25811
25812
25813
25814
25815 )
25816 (Lisp_Object buffer)
25817 {
25818 struct buffer *buf = current_buffer;
25819 struct buffer *old = buf;
25820
25821 if (! NILP (buffer))
25822 {
25823 CHECK_BUFFER (buffer);
25824 buf = XBUFFER (buffer);
25825 }
25826
25827 if (NILP (BVAR (buf, bidi_display_reordering))
25828 || NILP (BVAR (buf, enable_multibyte_characters))
25829
25830
25831 || redisplay__inhibit_bidi)
25832 return Qleft_to_right;
25833 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25834 return BVAR (buf, bidi_paragraph_direction);
25835 else
25836 {
25837
25838
25839
25840 struct bidi_it itb;
25841 ptrdiff_t pos = BUF_PT (buf);
25842 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25843 int c;
25844 void *itb_data = bidi_shelve_cache ();
25845
25846 set_buffer_temp (buf);
25847
25848
25849
25850
25851
25852 if (pos >= ZV && pos > BEGV)
25853 dec_both (&pos, &bytepos);
25854 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25855 if (fast_looking_at (trailing_white_space,
25856 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25857 {
25858 while ((c = FETCH_BYTE (bytepos)) == '\n'
25859 || c == ' ' || c == '\t' || c == '\f')
25860 {
25861 if (bytepos <= BEGV_BYTE)
25862 break;
25863 bytepos--;
25864 pos--;
25865 }
25866 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25867 bytepos--;
25868 }
25869 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25870 itb.paragraph_dir = NEUTRAL_DIR;
25871 itb.string.s = NULL;
25872 itb.string.lstring = Qnil;
25873 itb.string.bufpos = 0;
25874 itb.string.from_disp_str = false;
25875 itb.string.unibyte = false;
25876
25877
25878
25879 itb.w = NULL;
25880 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25881 bidi_unshelve_cache (itb_data, false);
25882 set_buffer_temp (old);
25883 switch (itb.paragraph_dir)
25884 {
25885 case L2R:
25886 return Qleft_to_right;
25887 break;
25888 case R2L:
25889 return Qright_to_left;
25890 break;
25891 default:
25892 emacs_abort ();
25893 }
25894 }
25895 }
25896
25897 DEFUN ("bidi-find-overridden-directionality",
25898 Fbidi_find_overridden_directionality,
25899 Sbidi_find_overridden_directionality, 3, 4, 0,
25900 doc:
25901
25902
25903
25904
25905
25906
25907
25908
25909
25910
25911
25912
25913
25914
25915
25916
25917
25918
25919
25920
25921
25922
25923
25924
25925
25926
25927
25928
25929
25930
25931
25932
25933
25934
25935
25936
25937 )
25938 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
25939 {
25940 struct buffer *buf = current_buffer;
25941 struct buffer *old = buf;
25942 struct window *w = NULL;
25943 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
25944 struct bidi_it itb;
25945 ptrdiff_t from_pos, to_pos, from_bpos;
25946 void *itb_data;
25947
25948 if (!NILP (object))
25949 {
25950 if (BUFFERP (object))
25951 buf = XBUFFER (object);
25952 else if (WINDOWP (object))
25953 {
25954 w = decode_live_window (object);
25955 buf = XBUFFER (w->contents);
25956 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
25957 }
25958 else
25959 CHECK_STRING (object);
25960 }
25961
25962 if (STRINGP (object))
25963 {
25964
25965
25966 if (!STRING_MULTIBYTE (object)
25967
25968
25969
25970 || redisplay__inhibit_bidi)
25971 return Qnil;
25972
25973 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
25974 if (from_pos >= SCHARS (object))
25975 return Qnil;
25976
25977
25978 itb_data = bidi_shelve_cache ();
25979 itb.paragraph_dir = NEUTRAL_DIR;
25980 itb.string.lstring = object;
25981 itb.string.s = NULL;
25982 itb.string.schars = SCHARS (object);
25983 itb.string.bufpos = 0;
25984 itb.string.from_disp_str = false;
25985 itb.string.unibyte = false;
25986 itb.w = w;
25987 bidi_init_it (0, 0, frame_window_p, &itb);
25988 }
25989 else
25990 {
25991
25992
25993 if (NILP (BVAR (buf, bidi_display_reordering))
25994 || NILP (BVAR (buf, enable_multibyte_characters))
25995
25996
25997
25998 || redisplay__inhibit_bidi)
25999 return Qnil;
26000
26001 set_buffer_temp (buf);
26002 validate_region (&from, &to);
26003 from_pos = XFIXNUM (from);
26004 to_pos = XFIXNUM (to);
26005 if (from_pos >= ZV)
26006 return Qnil;
26007
26008
26009 itb_data = bidi_shelve_cache ();
26010 from_bpos = CHAR_TO_BYTE (from_pos);
26011 if (from_pos == BEGV)
26012 {
26013 itb.charpos = BEGV;
26014 itb.bytepos = BEGV_BYTE;
26015 }
26016 else if (FETCH_BYTE (from_bpos - 1) == '\n')
26017 {
26018 itb.charpos = from_pos;
26019 itb.bytepos = from_bpos;
26020 }
26021 else
26022 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
26023 -1, &itb.bytepos);
26024 itb.paragraph_dir = NEUTRAL_DIR;
26025 itb.string.s = NULL;
26026 itb.string.lstring = Qnil;
26027 itb.string.bufpos = 0;
26028 itb.string.from_disp_str = false;
26029 itb.string.unibyte = false;
26030 itb.w = w;
26031 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
26032 }
26033
26034 ptrdiff_t found;
26035 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
26036 do {
26037 bidi_paragraph_init (bdir, &itb, false);
26038 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
26039 ;
26040 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
26041
26042 bidi_unshelve_cache (itb_data, false);
26043 set_buffer_temp (old);
26044
26045 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
26046 }
26047
26048 DEFUN ("move-point-visually", Fmove_point_visually,
26049 Smove_point_visually, 1, 1, 0,
26050 doc:
26051
26052
26053
26054 )
26055 (Lisp_Object direction)
26056 {
26057 struct window *w = XWINDOW (selected_window);
26058 struct buffer *b = XBUFFER (w->contents);
26059 struct glyph_row *row;
26060 int dir;
26061 Lisp_Object paragraph_dir;
26062
26063 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
26064 (!(ROW)->continued_p \
26065 && NILP ((GLYPH)->object) \
26066 && (GLYPH)->type == CHAR_GLYPH \
26067 && (GLYPH)->u.ch == ' ' \
26068 && (GLYPH)->charpos >= 0 \
26069 && !(GLYPH)->avoid_cursor_p)
26070
26071 CHECK_FIXNUM (direction);
26072 dir = XFIXNUM (direction);
26073 if (dir > 0)
26074 dir = 1;
26075 else
26076 dir = -1;
26077
26078
26079
26080
26081 if (w->window_end_valid
26082 && !windows_or_buffers_changed
26083 && b
26084 && !b->clip_changed
26085 && !b->prevent_redisplay_optimizations_p
26086 && !window_outdated (w)
26087
26088
26089
26090 && w->last_point == BUF_PT (b)
26091 && w->cursor.vpos >= 0
26092 && w->cursor.vpos < w->current_matrix->nrows
26093 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
26094 {
26095 struct glyph *g = row->glyphs[TEXT_AREA];
26096 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
26097 struct glyph *gpt = g + w->cursor.hpos;
26098
26099 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
26100 {
26101 if (BUFFERP (g->object) && g->charpos != PT)
26102 {
26103 SET_PT (g->charpos);
26104 w->cursor.vpos = -1;
26105 return make_fixnum (PT);
26106 }
26107 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
26108 {
26109 ptrdiff_t new_pos;
26110
26111 if (BUFFERP (gpt->object))
26112 {
26113 new_pos = PT;
26114 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
26115 new_pos += (row->reversed_p ? -dir : dir);
26116 else
26117 new_pos -= (row->reversed_p ? -dir : dir);
26118 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
26119
26120
26121 if (new_pos == PT)
26122 break;
26123 }
26124 else if (BUFFERP (g->object))
26125 new_pos = g->charpos;
26126 else
26127 break;
26128 SET_PT (new_pos);
26129 w->cursor.vpos = -1;
26130 return make_fixnum (PT);
26131 }
26132 else if (ROW_GLYPH_NEWLINE_P (row, g))
26133 {
26134
26135
26136
26137 if (g->charpos > 0)
26138 SET_PT (g->charpos);
26139 else if (row->ends_at_zv_p && PT != ZV)
26140 SET_PT (ZV);
26141 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
26142 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26143 else
26144 break;
26145 w->cursor.vpos = -1;
26146 return make_fixnum (PT);
26147 }
26148 }
26149 if (g == e || NILP (g->object))
26150 {
26151 if (row->truncated_on_left_p || row->truncated_on_right_p)
26152 goto simulate_display;
26153 if (!row->reversed_p)
26154 row += dir;
26155 else
26156 row -= dir;
26157 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
26158 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
26159 goto simulate_display;
26160
26161 if (dir > 0)
26162 {
26163 if (row->reversed_p && !row->continued_p)
26164 {
26165 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26166 w->cursor.vpos = -1;
26167 return make_fixnum (PT);
26168 }
26169 g = row->glyphs[TEXT_AREA];
26170 e = g + row->used[TEXT_AREA];
26171 for ( ; g < e; g++)
26172 {
26173 if (BUFFERP (g->object)
26174
26175
26176
26177 || ROW_GLYPH_NEWLINE_P (row, g)
26178
26179
26180 || (row->ends_at_zv_p
26181 && !row->reversed_p
26182 && NILP (g->object)
26183 && g->type == CHAR_GLYPH
26184 && g->u.ch == ' '))
26185 {
26186 if (g->charpos > 0)
26187 SET_PT (g->charpos);
26188 else if (!row->reversed_p
26189 && row->ends_at_zv_p
26190 && PT != ZV)
26191 SET_PT (ZV);
26192 else
26193 continue;
26194 w->cursor.vpos = -1;
26195 return make_fixnum (PT);
26196 }
26197 }
26198 }
26199 else
26200 {
26201 if (!row->reversed_p && !row->continued_p)
26202 {
26203 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26204 w->cursor.vpos = -1;
26205 return make_fixnum (PT);
26206 }
26207 e = row->glyphs[TEXT_AREA];
26208 g = e + row->used[TEXT_AREA] - 1;
26209 for ( ; g >= e; g--)
26210 {
26211 if (BUFFERP (g->object)
26212 || (ROW_GLYPH_NEWLINE_P (row, g)
26213 && g->charpos > 0)
26214
26215
26216
26217 || g->type == STRETCH_GLYPH
26218 || (row->ends_at_zv_p
26219 && row->reversed_p
26220 && NILP (g->object)
26221 && g->type == CHAR_GLYPH
26222 && g->u.ch == ' '))
26223 {
26224 if (g->charpos > 0)
26225 SET_PT (g->charpos);
26226 else if (row->reversed_p
26227 && row->ends_at_zv_p
26228 && PT != ZV)
26229 SET_PT (ZV);
26230 else
26231 continue;
26232 w->cursor.vpos = -1;
26233 return make_fixnum (PT);
26234 }
26235 }
26236 }
26237 }
26238 }
26239
26240 simulate_display:
26241
26242
26243
26244
26245 if (b)
26246 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26247 else
26248 paragraph_dir = Qleft_to_right;
26249 if (EQ (paragraph_dir, Qright_to_left))
26250 dir = -dir;
26251 if (PT <= BEGV && dir < 0)
26252 xsignal0 (Qbeginning_of_buffer);
26253 else if (PT >= ZV && dir > 0)
26254 xsignal0 (Qend_of_buffer);
26255 else
26256 {
26257 struct text_pos pt;
26258 struct it it;
26259 int pt_x, target_x, pixel_width, pt_vpos;
26260 bool at_eol_p;
26261 bool overshoot_expected = false;
26262 bool target_is_eol_p = false;
26263 void *itdata = bidi_shelve_cache ();
26264
26265
26266 SET_TEXT_POS (pt, PT, PT_BYTE);
26267 start_display (&it, w, pt);
26268
26269
26270
26271
26272
26273
26274 if (it.line_wrap == TRUNCATE)
26275 it.last_visible_x = DISP_INFINITY;
26276
26277 if (it.cmp_it.id < 0
26278 && it.method == GET_FROM_STRING
26279 && it.area == TEXT_AREA
26280 && it.string_from_display_prop_p
26281 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26282 overshoot_expected = true;
26283
26284
26285
26286
26287
26288 reseat:
26289 reseat_at_previous_visible_line_start (&it);
26290 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26291 if (IT_CHARPOS (it) != PT)
26292 {
26293 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26294 -1, -1, -1, MOVE_TO_POS);
26295
26296
26297
26298 if (it.method == GET_FROM_DISPLAY_VECTOR
26299 && it.current.dpvec_index > 0
26300 && !overshoot_expected)
26301 {
26302 overshoot_expected = true;
26303 goto reseat;
26304 }
26305 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26306 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26307 }
26308 pt_x = it.current_x;
26309 pt_vpos = it.vpos;
26310 if (dir > 0 || overshoot_expected)
26311 {
26312 struct glyph_row *row = it.glyph_row;
26313
26314
26315
26316
26317 if (pt_x == 0)
26318 get_next_display_element (&it);
26319 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26320 it.glyph_row = NULL;
26321 PRODUCE_GLYPHS (&it);
26322 it.glyph_row = row;
26323
26324
26325
26326 it.current_x = pt_x;
26327 }
26328 else
26329 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26330 pixel_width = it.pixel_width;
26331 if (overshoot_expected && at_eol_p)
26332 pixel_width = 0;
26333 else if (pixel_width <= 0)
26334 pixel_width = 1;
26335
26336
26337
26338
26339 if (overshoot_expected)
26340 {
26341 if (it.bidi_p)
26342 pt_x += pixel_width * it.bidi_it.scan_dir;
26343 else
26344 pt_x += pixel_width;
26345 }
26346
26347
26348
26349
26350
26351
26352
26353 if (dir > 0)
26354 target_x = pt_x + pixel_width;
26355 else
26356 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26357
26358
26359
26360
26361
26362 if (dir < 0)
26363 {
26364 if (pt_x > 0)
26365 {
26366 start_display (&it, w, pt);
26367 if (it.line_wrap == TRUNCATE)
26368 it.last_visible_x = DISP_INFINITY;
26369 reseat_at_previous_visible_line_start (&it);
26370 it.current_x = it.current_y = it.hpos = 0;
26371 if (pt_vpos != 0)
26372 move_it_by_lines (&it, pt_vpos);
26373 }
26374 else
26375 {
26376 move_it_by_lines (&it, -1);
26377 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26378 target_is_eol_p = true;
26379
26380
26381
26382
26383
26384
26385
26386
26387
26388
26389 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26390 {
26391 void *it_data = NULL;
26392 struct it it2;
26393
26394 SAVE_IT (it2, it, it_data);
26395 move_it_in_display_line_to (&it, ZV, target_x,
26396 MOVE_TO_POS | MOVE_TO_X);
26397
26398
26399 if (it.current_x != target_x)
26400 target_x = it.current_x - 1;
26401 RESTORE_IT (&it, &it2, it_data);
26402 }
26403 }
26404 }
26405 else
26406 {
26407 if (at_eol_p
26408 || (target_x >= it.last_visible_x
26409 && it.line_wrap != TRUNCATE))
26410 {
26411 if (pt_x > 0)
26412 move_it_by_lines (&it, 0);
26413 move_it_by_lines (&it, 1);
26414 target_x = 0;
26415 }
26416 }
26417
26418
26419
26420
26421
26422
26423
26424 if (FRAME_WINDOW_P (it.f) && dir < 0)
26425 {
26426 struct text_pos new_pos;
26427 enum move_it_result rc = MOVE_X_REACHED;
26428
26429 if (it.current_x == 0)
26430 get_next_display_element (&it);
26431 if (it.what == IT_COMPOSITION)
26432 {
26433 new_pos.charpos = it.cmp_it.charpos;
26434 new_pos.bytepos = -1;
26435 }
26436 else
26437 new_pos = it.current.pos;
26438
26439 while (it.current_x + it.pixel_width <= target_x
26440 && (rc == MOVE_X_REACHED
26441
26442
26443
26444 || (it.line_wrap == WORD_WRAP
26445 && rc == MOVE_POS_MATCH_OR_ZV)))
26446 {
26447 int new_x = it.current_x + it.pixel_width;
26448
26449
26450
26451
26452
26453
26454
26455 if (it.what == IT_COMPOSITION)
26456 {
26457 new_pos.charpos = it.cmp_it.charpos;
26458 new_pos.bytepos = -1;
26459 }
26460 else
26461 new_pos = it.current.pos;
26462 if (new_x == it.current_x)
26463 new_x++;
26464 rc = move_it_in_display_line_to (&it, ZV, new_x,
26465 MOVE_TO_POS | MOVE_TO_X);
26466 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26467 break;
26468 }
26469
26470
26471 if (new_pos.bytepos == -1)
26472 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26473 it.current.pos = new_pos;
26474 }
26475 else if (it.current_x != target_x)
26476 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26477
26478
26479
26480 if (dir > 0)
26481 {
26482 while (IT_CHARPOS (it) == PT)
26483 {
26484 set_iterator_to_next (&it, false);
26485 if (!get_next_display_element (&it))
26486 break;
26487 }
26488 }
26489
26490
26491 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26492 bidi_unshelve_cache (itdata, false);
26493 }
26494
26495 return make_fixnum (PT);
26496
26497 #undef ROW_GLYPH_NEWLINE_P
26498 }
26499
26500 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26501 Sbidi_resolved_levels, 0, 1, 0,
26502 doc:
26503
26504
26505
26506
26507
26508
26509
26510
26511
26512
26513
26514
26515
26516
26517
26518
26519
26520
26521
26522
26523
26524
26525
26526
26527
26528 )
26529 (Lisp_Object vpos)
26530 {
26531 struct window *w = XWINDOW (selected_window);
26532 struct buffer *b = XBUFFER (w->contents);
26533 int nrow;
26534 struct glyph_row *row;
26535
26536 if (NILP (vpos))
26537 {
26538 int d1, d2, d3, d4, d5;
26539
26540 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26541 }
26542 else
26543 {
26544 CHECK_FIXNUM (vpos);
26545 nrow = XFIXNUM (vpos);
26546 }
26547
26548
26549 if (w->window_end_valid
26550 && !windows_or_buffers_changed
26551 && b
26552 && !b->clip_changed
26553 && !b->prevent_redisplay_optimizations_p
26554 && !window_outdated (w)
26555 && nrow >= 0
26556 && nrow < w->current_matrix->nrows
26557 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26558 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26559 {
26560 struct glyph *g, *e, *g1;
26561 int nglyphs, i;
26562 Lisp_Object levels;
26563
26564 if (!row->reversed_p)
26565 {
26566 g = g1 = row->glyphs[TEXT_AREA];
26567 e = g + row->used[TEXT_AREA];
26568
26569
26570
26571 while (g < e
26572 && NILP (g->object)
26573 && g->charpos < 0)
26574 g++;
26575 g1 = g;
26576
26577
26578 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26579 nglyphs++;
26580
26581
26582 levels = make_uninit_vector (nglyphs);
26583 for (i = 0; g1 < g; i++, g1++)
26584 ASET (levels, i, make_fixnum (g1->resolved_level));
26585 }
26586 else
26587 {
26588 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26589 e = row->glyphs[TEXT_AREA] - 1;
26590 while (g > e
26591 && NILP (g->object)
26592 && g->charpos < 0)
26593 g--;
26594 g1 = g;
26595 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26596 nglyphs++;
26597 levels = make_uninit_vector (nglyphs);
26598 for (i = 0; g1 > g; i++, g1--)
26599 ASET (levels, i, make_fixnum (g1->resolved_level));
26600 }
26601 return levels;
26602 }
26603 else
26604 return Qnil;
26605 }
26606
26607
26608
26609
26610
26611
26612
26613
26614
26615
26616
26617
26618
26619
26620
26621
26622
26623 static void
26624 display_menu_bar (struct window *w)
26625 {
26626 struct frame *f = XFRAME (WINDOW_FRAME (w));
26627 struct it it;
26628 Lisp_Object items;
26629 int i;
26630
26631
26632 #ifdef HAVE_NTGUI
26633 if (FRAME_W32_P (f))
26634 return;
26635 #endif
26636 #if defined (HAVE_PGTK)
26637 if (FRAME_PGTK_P (f))
26638 return;
26639 #endif
26640
26641 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26642 if (FRAME_X_P (f))
26643 return;
26644 #endif
26645
26646 #ifdef HAVE_NS
26647 if (FRAME_NS_P (f))
26648 return;
26649 #endif
26650
26651 #ifdef HAVE_HAIKU
26652 if (FRAME_HAIKU_P (f))
26653 return;
26654 #endif
26655
26656 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26657 eassert (!FRAME_WINDOW_P (f));
26658 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26659 it.first_visible_x = 0;
26660 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26661 #elif defined (HAVE_X_WINDOWS) || defined (HAVE_ANDROID)
26662 struct window *menu_window = NULL;
26663 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
26664
26665 if (FRAME_WINDOW_P (f))
26666 {
26667
26668
26669 menu_window = XWINDOW (f->menu_bar_window);
26670 init_iterator (&it, menu_window, -1, -1,
26671 menu_window->desired_matrix->rows,
26672 MENU_FACE_ID);
26673 }
26674 else
26675 #endif
26676 {
26677
26678
26679 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26680 MENU_FACE_ID);
26681 it.first_visible_x = 0;
26682 it.last_visible_x = FRAME_COLS (f);
26683 }
26684
26685
26686
26687
26688 it.paragraph_embedding = L2R;
26689
26690
26691 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26692 {
26693 struct glyph_row *row = it.glyph_row + i;
26694 clear_glyph_row (row);
26695 row->enabled_p = true;
26696 row->full_width_p = true;
26697 row->reversed_p = false;
26698 }
26699
26700
26701 items = FRAME_MENU_BAR_ITEMS (it.f);
26702 for (i = 0; i < ASIZE (items); i += 4)
26703 {
26704 Lisp_Object string;
26705
26706
26707 string = AREF (items, i + 1);
26708 if (NILP (string))
26709 break;
26710
26711
26712 ASET (items, i + 3, make_fixnum (it.hpos));
26713
26714
26715 if (it.current_x < it.last_visible_x)
26716 display_string (NULL, string, Qnil, 0, 0, &it,
26717 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26718 }
26719
26720
26721 if (it.current_x < it.last_visible_x)
26722 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26723
26724
26725 compute_line_metrics (&it);
26726 it.glyph_row->full_width_p = true;
26727 it.glyph_row->continued_p = false;
26728 it.glyph_row->truncated_on_left_p = false;
26729 it.glyph_row->truncated_on_right_p = false;
26730
26731
26732
26733
26734
26735 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
26736
26737 extend_face_to_end_of_line (&it);
26738 if (face->box != FACE_NO_BOX)
26739 {
26740 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26741 + it.glyph_row->used[TEXT_AREA] - 1);
26742 int box_thickness = face->box_vertical_line_width;
26743 last->right_box_line_p = true;
26744
26745
26746
26747
26748
26749
26750 if (box_thickness > 0)
26751 last->pixel_width += max (0, (box_thickness
26752 - (it.current_x - it.last_visible_x)));
26753 }
26754
26755
26756
26757 if (FRAME_WINDOW_P (it.f) && menu_window)
26758 {
26759 struct glyph_row *row;
26760 int delta_height;
26761
26762 row = it.glyph_row;
26763 delta_height
26764 = ((row->y + row->height)
26765 - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
26766
26767 if (delta_height != 0)
26768 {
26769 FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
26770 adjust_frame_size (it.f, -1, -1, 3, false, Qmenu_bar_lines);
26771 }
26772 }
26773 #endif
26774 }
26775
26776
26777
26778
26779 #ifndef HAVE_ANDROID
26780
26781
26782 static void
26783 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26784 {
26785 struct glyph *pointers[1 + LAST_AREA];
26786 int to_used = to->used[TEXT_AREA];
26787
26788
26789 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26790
26791
26792 *to = *from;
26793
26794
26795 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26796
26797
26798 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26799 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26800
26801
26802
26803 if (to_used > from->used[TEXT_AREA])
26804 fill_up_frame_row_with_spaces (to, to_used);
26805 }
26806
26807
26808
26809
26810
26811
26812
26813
26814
26815
26816
26817
26818
26819
26820
26821
26822
26823
26824
26825
26826
26827
26828 void
26829 display_tty_menu_item (const char *item_text, int width, int face_id,
26830 int x, int y, bool submenu)
26831 {
26832 struct it it;
26833 struct frame *f = SELECTED_FRAME ();
26834 struct window *w = XWINDOW (f->selected_window);
26835 struct glyph_row *row;
26836 size_t item_len = strlen (item_text);
26837
26838 eassert (FRAME_TERMCAP_P (f));
26839
26840
26841
26842
26843
26844
26845 if (y >= f->desired_matrix->nrows)
26846 return;
26847
26848 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26849 it.first_visible_x = 0;
26850 it.last_visible_x = FRAME_COLS (f) - 1;
26851 row = it.glyph_row;
26852
26853 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26854 bool saved_width = row->full_width_p;
26855 row->full_width_p = true;
26856 bool saved_reversed = row->reversed_p;
26857 row->reversed_p = false;
26858 row->enabled_p = true;
26859
26860
26861
26862 eassert (x < f->desired_matrix->matrix_w);
26863 it.current_x = it.hpos = x;
26864 it.current_y = it.vpos = y;
26865 int saved_used = row->used[TEXT_AREA];
26866 bool saved_truncated = row->truncated_on_right_p;
26867 row->used[TEXT_AREA] = x;
26868 it.face_id = face_id;
26869 it.line_wrap = TRUNCATE;
26870
26871
26872
26873
26874
26875
26876 it.paragraph_embedding = L2R;
26877
26878
26879 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26880 width--;
26881
26882 if (submenu)
26883 {
26884 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26885 item_len, 0, FRAME_COLS (f) - 1, -1);
26886 width -= item_len;
26887
26888 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26889 FRAME_COLS (f) - 1, -1);
26890 }
26891 else
26892 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26893 width, 0, FRAME_COLS (f) - 1, -1);
26894
26895 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26896 row->truncated_on_right_p = saved_truncated;
26897 row->hash = row_hash (row);
26898 row->full_width_p = saved_width;
26899 row->reversed_p = saved_reversed;
26900 }
26901
26902 #endif
26903
26904
26905
26906
26907
26908
26909
26910
26911
26912
26913
26914 static int
26915 redisplay_mode_lines (Lisp_Object window, bool force)
26916 {
26917 int nwindows = 0;
26918
26919 while (!NILP (window))
26920 {
26921 struct window *w = XWINDOW (window);
26922
26923 if (WINDOWP (w->contents))
26924 nwindows += redisplay_mode_lines (w->contents, force);
26925 else if (force
26926 || FRAME_GARBAGED_P (XFRAME (w->frame))
26927 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26928 {
26929 struct text_pos lpoint;
26930 struct buffer *old = current_buffer;
26931
26932
26933 SET_TEXT_POS (lpoint, PT, PT_BYTE);
26934 set_buffer_internal_1 (XBUFFER (w->contents));
26935
26936
26937
26938 if (!EQ (window, selected_window))
26939 {
26940 struct text_pos pt;
26941
26942 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
26943 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
26944 }
26945
26946
26947 clear_glyph_matrix (w->desired_matrix);
26948 if (display_mode_lines (w))
26949 ++nwindows;
26950
26951
26952 set_buffer_internal_1 (old);
26953 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
26954 }
26955
26956 window = w->next;
26957 }
26958
26959 return nwindows;
26960 }
26961
26962
26963
26964
26965
26966
26967 static int
26968 display_mode_lines (struct window *w)
26969 {
26970 Lisp_Object old_selected_window = selected_window;
26971 Lisp_Object new_frame = w->frame;
26972 specpdl_ref count = SPECPDL_INDEX ();
26973 int n = 0;
26974
26975 record_unwind_protect (restore_selected_window, selected_window);
26976 record_unwind_protect
26977 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
26978
26979 if (window_wants_mode_line (w))
26980 {
26981 Lisp_Object window;
26982 Lisp_Object default_help
26983 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
26984
26985
26986
26987 XSETWINDOW (window, w);
26988 if (FUNCTIONP (default_help))
26989 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
26990 else if (STRINGP (default_help))
26991 wset_mode_line_help_echo (w, default_help);
26992 else
26993 wset_mode_line_help_echo (w, Qnil);
26994 }
26995
26996 selected_frame = new_frame;
26997
26998
26999 XSETWINDOW (selected_window, w);
27000 XFRAME (new_frame)->selected_window = selected_window;
27001
27002
27003 line_number_displayed = false;
27004 w->column_number_displayed = -1;
27005
27006 if (window_wants_mode_line (w))
27007 {
27008 Lisp_Object window_mode_line_format
27009 = window_parameter (w, Qmode_line_format);
27010 struct window *sel_w = XWINDOW (old_selected_window);
27011
27012
27013 display_mode_line (w,
27014 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
27015 NILP (window_mode_line_format)
27016 ? BVAR (current_buffer, mode_line_format)
27017 : window_mode_line_format);
27018 ++n;
27019 }
27020
27021 if (window_wants_tab_line (w))
27022 {
27023 Lisp_Object window_tab_line_format
27024 = window_parameter (w, Qtab_line_format);
27025
27026 display_mode_line (w, TAB_LINE_FACE_ID,
27027 NILP (window_tab_line_format)
27028 ? BVAR (current_buffer, tab_line_format)
27029 : window_tab_line_format);
27030 ++n;
27031 }
27032
27033 if (window_wants_header_line (w))
27034 {
27035 Lisp_Object window_header_line_format
27036 = window_parameter (w, Qheader_line_format);
27037
27038 display_mode_line (w, HEADER_LINE_FACE_ID,
27039 NILP (window_header_line_format)
27040 ? BVAR (current_buffer, header_line_format)
27041 : window_header_line_format);
27042 ++n;
27043 }
27044
27045 unbind_to (count, Qnil);
27046
27047 if (n > 0)
27048 w->must_be_updated_p = true;
27049 return n;
27050 }
27051
27052
27053
27054
27055
27056
27057
27058
27059 static int
27060 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
27061 {
27062 struct it it;
27063 struct face *face;
27064 specpdl_ref count = SPECPDL_INDEX ();
27065
27066 init_iterator (&it, w, -1, -1, NULL, face_id);
27067
27068
27069 it.glyph_row->enabled_p = false;
27070 prepare_desired_row (w, it.glyph_row, true);
27071
27072 it.glyph_row->mode_line_p = true;
27073 if (face_id == TAB_LINE_FACE_ID)
27074 {
27075 it.glyph_row->tab_line_p = true;
27076 w->desired_matrix->tab_line_p = true;
27077 }
27078 else if (face_id == HEADER_LINE_FACE_ID)
27079 w->desired_matrix->header_line_p = true;
27080
27081
27082
27083
27084 it.paragraph_embedding = L2R;
27085
27086 record_unwind_protect (unwind_format_mode_line,
27087 format_mode_line_unwind_data (NULL, NULL,
27088 Qnil, false));
27089
27090
27091
27092
27093 push_kboard (FRAME_KBOARD (it.f));
27094 record_unwind_save_match_data ();
27095
27096 if (NILP (Vmode_line_compact)
27097 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
27098 {
27099 mode_line_target = MODE_LINE_DISPLAY;
27100 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27101 }
27102 else
27103 {
27104 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
27105 if (EQ (Vmode_line_compact, Qlong)
27106 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
27107 {
27108
27109
27110 display_string (NULL, mode_string, Qnil,
27111 0, 0, &it, 0, 0, 0,
27112 STRING_MULTIBYTE (mode_string));
27113 }
27114 else
27115 {
27116
27117 ptrdiff_t i = 0, i_byte = 0, start = 0;
27118 int prev = 0;
27119
27120 while (i < SCHARS (mode_string))
27121 {
27122 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
27123 if (c == ' ' && prev == ' ')
27124 {
27125 display_string (NULL,
27126 Fsubstring (mode_string, make_fixnum (start),
27127 make_fixnum (i - 1)),
27128 Qnil, 0, 0, &it, 0, 0, 0,
27129 STRING_MULTIBYTE (mode_string));
27130
27131 while (c == ' ' && i < SCHARS (mode_string))
27132 c = fetch_string_char_advance (mode_string, &i, &i_byte);
27133 start = i - 1;
27134 }
27135 prev = c;
27136 }
27137
27138
27139 if (start < i)
27140 display_string (NULL,
27141 Fsubstring (mode_string, make_fixnum (start),
27142 make_fixnum (i)),
27143 Qnil, 0, 0, &it, 0, 0, 0,
27144 STRING_MULTIBYTE (mode_string));
27145 }
27146 }
27147 pop_kboard ();
27148
27149 unbind_to (count, Qnil);
27150
27151
27152 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
27153
27154 compute_line_metrics (&it);
27155 it.glyph_row->full_width_p = true;
27156 it.glyph_row->continued_p = false;
27157 it.glyph_row->truncated_on_left_p = false;
27158 it.glyph_row->truncated_on_right_p = false;
27159
27160
27161 face = FACE_FROM_ID (it.f, face_id);
27162 extend_face_to_end_of_line (&it);
27163 if (face->box != FACE_NO_BOX)
27164 {
27165 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
27166 + it.glyph_row->used[TEXT_AREA] - 1);
27167 int box_thickness = face->box_vertical_line_width;
27168 last->right_box_line_p = true;
27169
27170
27171
27172
27173
27174
27175 if (box_thickness > 0)
27176 last->pixel_width += max (0, (box_thickness
27177 - (it.current_x - it.last_visible_x)));
27178 }
27179
27180 return it.glyph_row->height;
27181 }
27182
27183
27184
27185
27186 static Lisp_Object
27187 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
27188 {
27189 register Lisp_Object tail, prev;
27190 register Lisp_Object tem;
27191
27192 tail = list;
27193 prev = Qnil;
27194 while (CONSP (tail))
27195 {
27196 tem = XCAR (tail);
27197
27198 if (EQ (elt, tem))
27199 {
27200
27201 if (NILP (prev))
27202 list = XCDR (tail);
27203 else
27204 Fsetcdr (prev, XCDR (tail));
27205
27206
27207 Fsetcdr (tail, list);
27208 return tail;
27209 }
27210 else
27211 prev = tail;
27212 tail = XCDR (tail);
27213 maybe_quit ();
27214 }
27215
27216
27217 return list;
27218 }
27219
27220
27221
27222
27223
27224 static Lisp_Object
27225 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
27226 {
27227 eassert (nargs == 4);
27228 return Fset_text_properties (args[0], args[1], args[2], args[3]);
27229 }
27230
27231
27232
27233
27234
27235
27236
27237
27238
27239
27240
27241
27242
27243
27244
27245
27246
27247
27248
27249
27250
27251
27252
27253
27254
27255 static int
27256 display_mode_element (struct it *it, int depth, int field_width, int precision,
27257 Lisp_Object elt, Lisp_Object props, bool risky)
27258 {
27259 int n = 0, field, prec;
27260 bool literal = false;
27261
27262 tail_recurse:
27263 if (depth > 100)
27264 elt = build_string ("*too-deep*");
27265
27266 depth++;
27267
27268 switch (XTYPE (elt))
27269 {
27270 case Lisp_String:
27271 {
27272
27273 unsigned char c;
27274 ptrdiff_t offset = 0;
27275
27276 if (SCHARS (elt) > 0
27277 && (!NILP (props) || risky))
27278 {
27279 Lisp_Object oprops, aelt;
27280 oprops = Ftext_properties_at (make_fixnum (0), elt);
27281
27282
27283
27284
27285
27286 if (NILP (Fequal (props, oprops)) || risky)
27287 {
27288
27289
27290 if (! NILP (oprops) && !risky)
27291 {
27292 Lisp_Object tem;
27293
27294 oprops = Fcopy_sequence (oprops);
27295 tem = props;
27296 while (CONSP (tem))
27297 {
27298 oprops = plist_put (oprops, XCAR (tem),
27299 XCAR (XCDR (tem)));
27300 tem = XCDR (XCDR (tem));
27301 }
27302 props = oprops;
27303 }
27304
27305 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27306 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27307 {
27308
27309
27310 elt = XCAR (aelt);
27311 mode_line_proptrans_alist
27312 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27313 }
27314 else
27315 {
27316 Lisp_Object tem;
27317
27318
27319
27320 if (! NILP (aelt))
27321 mode_line_proptrans_alist
27322 = Fdelq (aelt, mode_line_proptrans_alist);
27323
27324 elt = Fcopy_sequence (elt);
27325
27326
27327
27328 internal_condition_case_n (safe_set_text_properties,
27329 4,
27330 ((Lisp_Object [])
27331 {make_fixnum (0),
27332 Flength (elt),
27333 props,
27334 elt}),
27335 Qt, safe_eval_handler);
27336
27337 mode_line_proptrans_alist
27338 = Fcons (Fcons (elt, props),
27339 mode_line_proptrans_alist);
27340
27341
27342 tem = Fnthcdr (make_fixnum (50),
27343 mode_line_proptrans_alist);
27344 if (! NILP (tem))
27345 XSETCDR (tem, Qnil);
27346 }
27347 }
27348 }
27349
27350 offset = 0;
27351
27352 if (literal)
27353 {
27354 prec = precision - n;
27355 switch (mode_line_target)
27356 {
27357 case MODE_LINE_NOPROP:
27358 case MODE_LINE_TITLE:
27359 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27360 break;
27361 case MODE_LINE_STRING:
27362 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27363 break;
27364 case MODE_LINE_DISPLAY:
27365 n += display_string (NULL, elt, Qnil, 0, 0, it,
27366 0, prec, 0, STRING_MULTIBYTE (elt));
27367 break;
27368 }
27369
27370 break;
27371 }
27372
27373
27374
27375 while ((precision <= 0 || n < precision)
27376 && SREF (elt, offset) != 0
27377 && (mode_line_target != MODE_LINE_DISPLAY
27378 || it->current_x < it->last_visible_x))
27379 {
27380 ptrdiff_t last_offset = offset;
27381
27382
27383 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27384 ;
27385
27386 if (offset - 1 != last_offset)
27387 {
27388 ptrdiff_t nchars, nbytes;
27389
27390
27391
27392
27393 offset--;
27394
27395 prec = c_string_width (SDATA (elt) + last_offset,
27396 offset - last_offset, precision - n,
27397 &nchars, &nbytes);
27398
27399 switch (mode_line_target)
27400 {
27401 case MODE_LINE_NOPROP:
27402 case MODE_LINE_TITLE:
27403 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27404 break;
27405 case MODE_LINE_STRING:
27406 {
27407 ptrdiff_t bytepos = last_offset;
27408 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27409 ptrdiff_t endpos = (precision <= 0
27410 ? string_byte_to_char (elt, offset)
27411 : charpos + nchars);
27412 Lisp_Object mode_string
27413 = Fsubstring (elt, make_fixnum (charpos),
27414 make_fixnum (endpos));
27415 n += store_mode_line_string (NULL, mode_string, false,
27416 0, 0, Qnil);
27417 }
27418 break;
27419 case MODE_LINE_DISPLAY:
27420 {
27421 ptrdiff_t bytepos = last_offset;
27422 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27423
27424 if (precision <= 0)
27425 nchars = string_byte_to_char (elt, offset) - charpos;
27426 n += display_string (NULL, elt, Qnil, 0, charpos,
27427 it, 0, nchars, 0,
27428 STRING_MULTIBYTE (elt));
27429 }
27430 break;
27431 }
27432 }
27433 else
27434 {
27435 ptrdiff_t percent_position = offset;
27436
27437
27438
27439 field = 0;
27440 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27441 field = field * 10 + c - '0';
27442
27443
27444 if (field_width - n > 0 && field > field_width - n)
27445 field = field_width - n;
27446
27447
27448 prec = precision - n;
27449
27450 if (c == 'M')
27451 n += display_mode_element (it, depth, field, prec,
27452 Vglobal_mode_string, props,
27453 risky);
27454 else if (c != 0)
27455 {
27456 bool multibyte;
27457 ptrdiff_t bytepos, charpos;
27458 const char *spec;
27459 Lisp_Object string;
27460
27461 bytepos = percent_position;
27462 charpos = (STRING_MULTIBYTE (elt)
27463 ? string_byte_to_char (elt, bytepos)
27464 : bytepos);
27465 spec = decode_mode_spec (it->w, c, field, &string);
27466 eassert (NILP (string) || STRINGP (string));
27467 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27468
27469
27470 ptrdiff_t nbytes = strlen (spec);
27471 ptrdiff_t nchars, mb_nbytes;
27472 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27473 &nchars, &mb_nbytes);
27474 if (!(nbytes == nchars || nbytes != mb_nbytes))
27475 multibyte = true;
27476
27477 switch (mode_line_target)
27478 {
27479 case MODE_LINE_NOPROP:
27480 case MODE_LINE_TITLE:
27481 n += store_mode_line_noprop (spec, field, prec);
27482 break;
27483 case MODE_LINE_STRING:
27484 {
27485 Lisp_Object tem = build_string (spec);
27486 props = Ftext_properties_at (make_fixnum (charpos), elt);
27487
27488 n += store_mode_line_string (NULL, tem, false,
27489 field, prec, props);
27490 }
27491 break;
27492 case MODE_LINE_DISPLAY:
27493 {
27494 int nglyphs_before, nwritten;
27495
27496 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27497 nwritten = display_string (spec, string, elt,
27498 charpos, 0, it,
27499 field, prec, 0,
27500 multibyte);
27501
27502
27503
27504
27505 if (nwritten > 0)
27506 {
27507 struct glyph *glyph
27508 = (it->glyph_row->glyphs[TEXT_AREA]
27509 + nglyphs_before);
27510 int i;
27511
27512 for (i = 0; i < nwritten; ++i)
27513 {
27514 glyph[i].object = elt;
27515 glyph[i].charpos = charpos;
27516 }
27517
27518 n += nwritten;
27519 }
27520 }
27521 break;
27522 }
27523 }
27524 else
27525 break;
27526 }
27527 }
27528 }
27529 break;
27530
27531 case Lisp_Symbol:
27532
27533
27534
27535
27536 {
27537 register Lisp_Object tem;
27538
27539
27540
27541 if (NILP (Fget (elt, Qrisky_local_variable)))
27542 risky = true;
27543
27544 tem = Fboundp (elt);
27545 if (!NILP (tem))
27546 {
27547 tem = Fsymbol_value (elt);
27548
27549
27550 if (STRINGP (tem))
27551 literal = true;
27552
27553 if (!EQ (tem, elt))
27554 {
27555
27556 elt = tem;
27557 goto tail_recurse;
27558 }
27559 }
27560 }
27561 break;
27562
27563 case Lisp_Cons:
27564 {
27565 register Lisp_Object car, tem;
27566
27567
27568
27569
27570
27571
27572
27573
27574
27575
27576 car = XCAR (elt);
27577 if (EQ (car, QCeval))
27578 {
27579
27580
27581
27582 if (risky)
27583 break;
27584
27585 if (CONSP (XCDR (elt)))
27586 {
27587 Lisp_Object spec;
27588 spec = safe__eval (true, XCAR (XCDR (elt)));
27589
27590
27591
27592
27593
27594
27595 if (!FRAME_LIVE_P (it->f))
27596 signal_error (":eval deleted the frame being displayed", elt);
27597 n += display_mode_element (it, depth, field_width - n,
27598 precision - n, spec, props,
27599 risky);
27600 }
27601 }
27602 else if (EQ (car, QCpropertize))
27603 {
27604
27605
27606
27607 if (risky)
27608 break;
27609
27610 if (CONSP (XCDR (elt)))
27611 n += display_mode_element (it, depth, field_width - n,
27612 precision - n, XCAR (XCDR (elt)),
27613 XCDR (XCDR (elt)), risky);
27614 }
27615 else if (SYMBOLP (car))
27616 {
27617 tem = Fboundp (car);
27618 elt = XCDR (elt);
27619 if (!CONSP (elt))
27620 goto invalid;
27621
27622
27623 if (!NILP (tem))
27624 {
27625 tem = Fsymbol_value (car);
27626 if (!NILP (tem))
27627 {
27628 elt = XCAR (elt);
27629 goto tail_recurse;
27630 }
27631 }
27632
27633
27634
27635 elt = XCDR (elt);
27636 if (NILP (elt))
27637 break;
27638 else if (!CONSP (elt))
27639 goto invalid;
27640 elt = XCAR (elt);
27641 goto tail_recurse;
27642 }
27643 else if (FIXNUMP (car))
27644 {
27645 register int lim = XFIXNUM (car);
27646 elt = XCDR (elt);
27647 if (lim < 0)
27648 {
27649
27650 if (precision <= 0)
27651 precision = -lim;
27652 else
27653 precision = min (precision, -lim);
27654 }
27655 else if (lim > 0)
27656 {
27657
27658
27659 if (precision > 0)
27660 lim = min (precision, lim);
27661
27662
27663
27664
27665 field_width = max (lim, field_width);
27666 }
27667 goto tail_recurse;
27668 }
27669 else if (STRINGP (car) || CONSP (car))
27670 FOR_EACH_TAIL_SAFE (elt)
27671 {
27672 if (0 < precision && precision <= n)
27673 break;
27674 n += display_mode_element (it, depth,
27675
27676
27677 (! CONSP (XCDR (elt))
27678 ? field_width - n
27679 : 0),
27680 precision - n, XCAR (elt),
27681 props, risky);
27682 }
27683 }
27684 break;
27685
27686 default:
27687 invalid:
27688 elt = build_string ("*invalid*");
27689 goto tail_recurse;
27690 }
27691
27692
27693 if (field_width > 0 && n < field_width)
27694 {
27695 switch (mode_line_target)
27696 {
27697 case MODE_LINE_NOPROP:
27698 case MODE_LINE_TITLE:
27699 n += store_mode_line_noprop ("", field_width - n, 0);
27700 break;
27701 case MODE_LINE_STRING:
27702 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27703 Qnil);
27704 break;
27705 case MODE_LINE_DISPLAY:
27706 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27707 0, 0, 0);
27708 break;
27709 }
27710 }
27711
27712 return n;
27713 }
27714
27715
27716
27717
27718
27719
27720
27721
27722
27723
27724
27725
27726
27727
27728
27729
27730
27731
27732
27733
27734 static int
27735 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27736 bool copy_string,
27737 int field_width, int precision, Lisp_Object props)
27738 {
27739 ptrdiff_t len;
27740 int n = 0;
27741
27742 if (string != NULL)
27743 {
27744 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27745 lisp_string = make_string (string, len);
27746 if (NILP (props))
27747 props = mode_line_string_face_prop;
27748 else if (!NILP (mode_line_string_face))
27749 {
27750 Lisp_Object face = plist_get (props, Qface);
27751 props = Fcopy_sequence (props);
27752 if (NILP (face))
27753 face = mode_line_string_face;
27754 else
27755 face = list2 (face, mode_line_string_face);
27756 props = plist_put (props, Qface, face);
27757 }
27758 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27759 props, lisp_string);
27760 }
27761 else
27762 {
27763 len = SCHARS (lisp_string);
27764 if (precision > 0 && len > precision)
27765 {
27766 len = precision;
27767 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27768 precision = -1;
27769 }
27770 if (!NILP (mode_line_string_face))
27771 {
27772 Lisp_Object face;
27773 if (NILP (props))
27774 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27775 face = plist_get (props, Qface);
27776 if (NILP (face))
27777 face = mode_line_string_face;
27778 else
27779 face = list2 (face, mode_line_string_face);
27780 props = list2 (Qface, face);
27781 if (copy_string)
27782 lisp_string = Fcopy_sequence (lisp_string);
27783 }
27784 if (!NILP (props))
27785 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27786 props, lisp_string);
27787 }
27788
27789 if (len > 0)
27790 {
27791 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27792 n += len;
27793 }
27794
27795 if (field_width > len)
27796 {
27797 field_width -= len;
27798 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27799 Qnil);
27800 if (!NILP (props))
27801 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27802 props, lisp_string);
27803 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27804 n += field_width;
27805 }
27806
27807 return n;
27808 }
27809
27810
27811 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27812 1, 4, 0,
27813 doc:
27814
27815
27816
27817
27818
27819
27820
27821
27822
27823
27824
27825
27826
27827
27828
27829 )
27830 (Lisp_Object format, Lisp_Object face,
27831 Lisp_Object window, Lisp_Object buffer)
27832 {
27833 struct it it;
27834 int len;
27835 struct window *w;
27836 struct buffer *old_buffer = NULL;
27837 int face_id;
27838 bool no_props = FIXNUMP (face);
27839 specpdl_ref count = SPECPDL_INDEX ();
27840 Lisp_Object str;
27841 int string_start = 0;
27842
27843 w = decode_any_window (window);
27844 XSETWINDOW (window, w);
27845
27846 if (NILP (buffer))
27847 buffer = w->contents;
27848 CHECK_BUFFER (buffer);
27849
27850
27851
27852 if (NILP (format) || noninteractive)
27853 return empty_unibyte_string;
27854
27855 if (no_props)
27856 face = Qnil;
27857
27858 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27859 : EQ (face, Qt) ? (EQ (window, selected_window)
27860 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27861 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27862 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27863 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27864 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27865 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27866 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27867 : DEFAULT_FACE_ID;
27868
27869 old_buffer = current_buffer;
27870
27871
27872
27873 record_unwind_protect (unwind_format_mode_line,
27874 format_mode_line_unwind_data
27875 (XFRAME (WINDOW_FRAME (w)),
27876 old_buffer, selected_window, true));
27877 mode_line_proptrans_alist = Qnil;
27878
27879 Fselect_window (window, Qt);
27880 set_buffer_internal_1 (XBUFFER (buffer));
27881
27882 init_iterator (&it, w, -1, -1, NULL, face_id);
27883
27884 if (no_props)
27885 {
27886 mode_line_target = MODE_LINE_NOPROP;
27887 mode_line_string_face_prop = Qnil;
27888 mode_line_string_list = Qnil;
27889 string_start = MODE_LINE_NOPROP_LEN (0);
27890 }
27891 else
27892 {
27893 mode_line_target = MODE_LINE_STRING;
27894 mode_line_string_list = Qnil;
27895 mode_line_string_face = face;
27896 mode_line_string_face_prop
27897 = NILP (face) ? Qnil : list2 (Qface, face);
27898 }
27899
27900 push_kboard (FRAME_KBOARD (it.f));
27901 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27902 pop_kboard ();
27903
27904 if (no_props)
27905 {
27906 len = MODE_LINE_NOPROP_LEN (string_start);
27907 str = make_string (mode_line_noprop_buf + string_start, len);
27908 }
27909 else
27910 {
27911 mode_line_string_list = Fnreverse (mode_line_string_list);
27912 str = Fmapconcat (Qidentity, mode_line_string_list,
27913 empty_unibyte_string);
27914 }
27915
27916 return unbind_to (count, str);
27917 }
27918
27919
27920
27921
27922 static void
27923 pint2str (register char *buf, register int width, register ptrdiff_t d)
27924 {
27925 register char *p = buf;
27926
27927 if (d <= 0)
27928 *p++ = '0';
27929 else
27930 {
27931 while (d > 0)
27932 {
27933 *p++ = d % 10 + '0';
27934 d /= 10;
27935 }
27936 }
27937
27938 for (width -= (int) (p - buf); width > 0; --width)
27939 *p++ = ' ';
27940 *p-- = '\0';
27941 while (p > buf)
27942 {
27943 d = *buf;
27944 *buf++ = *p;
27945 *p-- = d;
27946 }
27947 }
27948
27949
27950
27951
27952
27953 static const char power_letter[] =
27954 {
27955 0,
27956 'k',
27957 'M',
27958 'G',
27959 'T',
27960 'P',
27961 'E',
27962 'Z',
27963 'Y',
27964 'R',
27965 'Q'
27966 };
27967
27968 static void
27969 pint2hrstr (char *buf, int width, ptrdiff_t d)
27970 {
27971
27972
27973 ptrdiff_t quotient = d;
27974 int remainder = 0;
27975
27976 int tenths = -1;
27977 int exponent = 0;
27978
27979
27980 int length;
27981
27982 char * psuffix;
27983 char * p;
27984
27985 if (quotient >= 1000)
27986 {
27987
27988 do
27989 {
27990 remainder = quotient % 1000;
27991 quotient /= 1000;
27992 exponent++;
27993 }
27994 while (quotient >= 1000);
27995
27996
27997 if (quotient <= 9)
27998 {
27999 tenths = remainder / 100;
28000 if (remainder % 100 >= 50)
28001 {
28002 if (tenths < 9)
28003 tenths++;
28004 else
28005 {
28006 quotient++;
28007 if (quotient == 10)
28008 tenths = -1;
28009 else
28010 tenths = 0;
28011 }
28012 }
28013 }
28014 else
28015 if (remainder >= 500)
28016 {
28017 if (quotient < 999)
28018 quotient++;
28019 else
28020 {
28021 quotient = 1;
28022 exponent++;
28023 tenths = 0;
28024 }
28025 }
28026 }
28027
28028
28029 if (tenths == -1 && quotient <= 99)
28030 if (quotient <= 9)
28031 length = 1;
28032 else
28033 length = 2;
28034 else
28035 length = 3;
28036 p = psuffix = buf + max (width, length);
28037
28038
28039 *psuffix++ = power_letter[exponent];
28040 *psuffix = '\0';
28041
28042
28043 if (tenths >= 0)
28044 {
28045 *--p = '0' + tenths;
28046 *--p = '.';
28047 }
28048
28049
28050 do
28051 {
28052 int digit = quotient % 10;
28053 *--p = '0' + digit;
28054 }
28055 while ((quotient /= 10) != 0);
28056
28057
28058 while (buf < p)
28059 *--p = ' ';
28060 }
28061
28062
28063
28064
28065
28066 static unsigned char invalid_eol_type[] = "(*invalid*)";
28067
28068 static char *
28069 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
28070 {
28071 Lisp_Object val;
28072 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
28073 const unsigned char *eol_str;
28074 int eol_str_len;
28075
28076 Lisp_Object eoltype;
28077
28078 val = CODING_SYSTEM_SPEC (coding_system);
28079 eoltype = Qnil;
28080
28081 if (!VECTORP (val))
28082 {
28083 *buf++ = multibyte ? '-' : ' ';
28084 if (eol_flag)
28085 eoltype = eol_mnemonic_undecided;
28086
28087 }
28088 else
28089 {
28090 Lisp_Object attrs;
28091 Lisp_Object eolvalue;
28092
28093 attrs = AREF (val, 0);
28094 eolvalue = AREF (val, 2);
28095
28096 if (multibyte)
28097 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
28098 (unsigned char *) buf);
28099 else
28100 *buf++ = ' ';
28101
28102 if (eol_flag)
28103 {
28104
28105
28106 if (NILP (eolvalue))
28107 eoltype = eol_mnemonic_undecided;
28108 else if (VECTORP (eolvalue))
28109 eoltype = eol_mnemonic_undecided;
28110 else
28111 eoltype = (EQ (eolvalue, Qunix)
28112 ? eol_mnemonic_unix
28113 : EQ (eolvalue, Qdos)
28114 ? eol_mnemonic_dos : eol_mnemonic_mac);
28115 }
28116 }
28117
28118 if (eol_flag)
28119 {
28120
28121 if (STRINGP (eoltype))
28122 {
28123 eol_str = SDATA (eoltype);
28124 eol_str_len = SBYTES (eoltype);
28125 }
28126 else if (CHARACTERP (eoltype))
28127 {
28128 int c = XFIXNAT (eoltype);
28129 return buf + CHAR_STRING (c, (unsigned char *) buf);
28130 }
28131 else
28132 {
28133 eol_str = invalid_eol_type;
28134 eol_str_len = sizeof (invalid_eol_type) - 1;
28135 }
28136 memcpy (buf, eol_str, eol_str_len);
28137 buf += eol_str_len;
28138 }
28139
28140 return buf;
28141 }
28142
28143
28144
28145
28146 static int
28147 percent99 (ptrdiff_t n, ptrdiff_t d)
28148 {
28149 int percent = (d - 1 + 100.0 * n) / d;
28150 return min (percent, 99);
28151 }
28152
28153
28154
28155
28156
28157
28158
28159
28160
28161 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
28162
28163 static const char *
28164 decode_mode_spec (struct window *w, register int c, int field_width,
28165 Lisp_Object *string)
28166 {
28167 Lisp_Object obj;
28168 struct frame *f = XFRAME (WINDOW_FRAME (w));
28169 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
28170
28171
28172
28173
28174
28175 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
28176 struct buffer *b = current_buffer;
28177
28178 obj = Qnil;
28179 *string = Qnil;
28180
28181 switch (c)
28182 {
28183 case '*':
28184 if (!NILP (BVAR (b, read_only)))
28185 return "%";
28186 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28187 return "*";
28188 return "-";
28189
28190 case '+':
28191
28192 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28193 return "*";
28194 if (!NILP (BVAR (b, read_only)))
28195 return "%";
28196 return "-";
28197
28198 case '&':
28199
28200 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28201 return "*";
28202 return "-";
28203
28204 case '%':
28205 return "%";
28206
28207 case '[':
28208 {
28209 int i;
28210 char *p;
28211
28212 if (command_loop_level > 5)
28213 return "[[[... ";
28214 p = decode_mode_spec_buf;
28215 for (i = 0; i < command_loop_level; i++)
28216 *p++ = '[';
28217 *p = 0;
28218 return decode_mode_spec_buf;
28219 }
28220
28221 case ']':
28222 {
28223 int i;
28224 char *p;
28225
28226 if (command_loop_level > 5)
28227 return " ...]]]";
28228 p = decode_mode_spec_buf;
28229 for (i = 0; i < command_loop_level; i++)
28230 *p++ = ']';
28231 *p = 0;
28232 return decode_mode_spec_buf;
28233 }
28234
28235 case '-':
28236 {
28237 register int i;
28238
28239
28240 if (mode_line_target == MODE_LINE_NOPROP
28241 || mode_line_target == MODE_LINE_STRING)
28242 return "--";
28243 if (field_width <= 0
28244 || field_width > sizeof (lots_of_dashes))
28245 {
28246 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28247 decode_mode_spec_buf[i] = '-';
28248 decode_mode_spec_buf[i] = '\0';
28249 return decode_mode_spec_buf;
28250 }
28251 else
28252 return lots_of_dashes;
28253 }
28254
28255 case 'b':
28256 obj = BVAR (b, name);
28257 break;
28258
28259 case 'c':
28260 case 'C':
28261
28262
28263
28264
28265
28266 if (mode_line_target == MODE_LINE_TITLE)
28267 return "";
28268 else
28269 {
28270 ptrdiff_t col = current_column ();
28271 int disp_col = (c == 'C') ? col + 1 : col;
28272 w->column_number_displayed = col;
28273 pint2str (decode_mode_spec_buf, width, disp_col);
28274 return decode_mode_spec_buf;
28275 }
28276
28277 case 'e':
28278 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28279 {
28280 if (NILP (Vmemory_full))
28281 return "";
28282 else
28283 return "!MEM FULL! ";
28284 }
28285 #else
28286 return "";
28287 #endif
28288
28289 case 'F':
28290
28291 if (!NILP (f->title))
28292 return SSDATA (f->title);
28293 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28294 return SSDATA (f->name);
28295 return "Emacs";
28296
28297 case 'f':
28298 obj = BVAR (b, filename);
28299 break;
28300
28301 case 'i':
28302 {
28303 ptrdiff_t size = ZV - BEGV;
28304 pint2str (decode_mode_spec_buf, width, size);
28305 return decode_mode_spec_buf;
28306 }
28307
28308 case 'I':
28309 {
28310 ptrdiff_t size = ZV - BEGV;
28311 pint2hrstr (decode_mode_spec_buf, width, size);
28312 return decode_mode_spec_buf;
28313 }
28314
28315 case 'l':
28316 {
28317 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28318 ptrdiff_t topline, nlines, height;
28319 ptrdiff_t junk;
28320
28321
28322 if (mode_line_target == MODE_LINE_TITLE)
28323 return "";
28324
28325 startpos = marker_position (w->start);
28326 startpos_byte = marker_byte_position (w->start);
28327 height = WINDOW_TOTAL_LINES (w);
28328
28329
28330
28331
28332
28333
28334
28335
28336 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28337 && startpos_byte <= BUF_ZV_BYTE (b)))
28338 {
28339 startpos = BUF_BEGV (b);
28340 startpos_byte = BUF_BEGV_BYTE (b);
28341 w->base_line_pos = 0;
28342 w->base_line_number = 0;
28343 }
28344
28345
28346
28347 if (w->base_line_pos == -1)
28348 goto no_value;
28349
28350
28351 if (FIXNUMP (Vline_number_display_limit)
28352 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28353 {
28354 w->base_line_pos = 0;
28355 w->base_line_number = 0;
28356 goto no_value;
28357 }
28358
28359 if (w->base_line_number > 0
28360 && w->base_line_pos > 0
28361 && w->base_line_pos <= startpos)
28362 {
28363 line = w->base_line_number;
28364 linepos = w->base_line_pos;
28365 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28366 }
28367 else
28368 {
28369 line = 1;
28370 linepos = BUF_BEGV (b);
28371 linepos_byte = BUF_BEGV_BYTE (b);
28372 }
28373
28374
28375 nlines = display_count_lines (linepos_byte,
28376 startpos_byte,
28377 startpos, &junk);
28378
28379 topline = nlines + line;
28380
28381
28382
28383
28384
28385 if (startpos == BUF_BEGV (b))
28386 {
28387 w->base_line_number = topline;
28388 w->base_line_pos = BUF_BEGV (b);
28389 }
28390 else if (nlines < height + 25 || nlines > height * 3 + 50
28391 || linepos == BUF_BEGV (b))
28392 {
28393 ptrdiff_t limit = BUF_BEGV (b);
28394 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28395 ptrdiff_t position;
28396 ptrdiff_t distance
28397 = (line_number_display_limit_width < 0 ? 0
28398 : ckd_mul (&distance, line_number_display_limit_width,
28399 height * 2 + 30)
28400 ? PTRDIFF_MAX : distance);
28401
28402 if (startpos - distance > limit)
28403 {
28404 limit = startpos - distance;
28405 limit_byte = CHAR_TO_BYTE (limit);
28406 }
28407
28408 nlines = display_count_lines (startpos_byte,
28409 limit_byte,
28410 - (height * 2 + 30),
28411 &position);
28412
28413
28414
28415 if (position == limit_byte && limit == startpos - distance)
28416 {
28417 w->base_line_pos = -1;
28418 w->base_line_number = 0;
28419 goto no_value;
28420 }
28421
28422 w->base_line_number = topline - nlines;
28423 w->base_line_pos = BYTE_TO_CHAR (position);
28424 }
28425
28426
28427 nlines = display_count_lines (startpos_byte,
28428 PT_BYTE, PT, &junk);
28429
28430
28431 line_number_displayed = true;
28432
28433
28434 pint2str (decode_mode_spec_buf, width, topline + nlines);
28435 return decode_mode_spec_buf;
28436 no_value:
28437 {
28438 char *p = decode_mode_spec_buf;
28439 int pad = width - 2;
28440 while (pad-- > 0)
28441 *p++ = ' ';
28442 *p++ = '?';
28443 *p++ = '?';
28444 *p = '\0';
28445 return decode_mode_spec_buf;
28446 }
28447 }
28448 break;
28449
28450 case 'm':
28451 obj = BVAR (b, mode_name);
28452 break;
28453
28454 case 'n':
28455 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28456 return " Narrow";
28457 break;
28458
28459
28460 case 'o':
28461 {
28462 ptrdiff_t toppos = marker_position (w->start);
28463 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28464 ptrdiff_t begv = BUF_BEGV (b);
28465 ptrdiff_t zv = BUF_ZV (b);
28466
28467 if (zv <= botpos)
28468 return toppos <= begv ? "All" : "Bottom";
28469 else if (toppos <= begv)
28470 return "Top";
28471 else
28472 {
28473 sprintf (decode_mode_spec_buf, "%2d%%",
28474 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28475 return decode_mode_spec_buf;
28476 }
28477 }
28478
28479
28480 case 'p':
28481 {
28482 ptrdiff_t pos = marker_position (w->start);
28483 ptrdiff_t begv = BUF_BEGV (b);
28484 ptrdiff_t zv = BUF_ZV (b);
28485
28486 if (w->window_end_pos <= BUF_Z (b) - zv)
28487 return pos <= begv ? "All" : "Bottom";
28488 else if (pos <= begv)
28489 return "Top";
28490 else
28491 {
28492 sprintf (decode_mode_spec_buf, "%2d%%",
28493 percent99 (pos - begv, zv - begv));
28494 return decode_mode_spec_buf;
28495 }
28496 }
28497
28498
28499 case 'P':
28500 {
28501 ptrdiff_t toppos = marker_position (w->start);
28502 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28503 ptrdiff_t begv = BUF_BEGV (b);
28504 ptrdiff_t zv = BUF_ZV (b);
28505
28506 if (zv <= botpos)
28507 return toppos <= begv ? "All" : "Bottom";
28508 else
28509 {
28510 sprintf (decode_mode_spec_buf,
28511 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28512 percent99 (botpos - begv, zv - begv));
28513 return decode_mode_spec_buf;
28514 }
28515 }
28516
28517
28518
28519 case 'q':
28520 {
28521 ptrdiff_t toppos = marker_position (w->start);
28522 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28523 ptrdiff_t begv = BUF_BEGV (b);
28524 ptrdiff_t zv = BUF_ZV (b);
28525 int top_perc, bot_perc;
28526
28527 if ((toppos <= begv) && (zv <= botpos))
28528 return "All ";
28529
28530 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28531 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28532
28533 if (top_perc == bot_perc)
28534 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28535 else
28536 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28537
28538 return decode_mode_spec_buf;
28539 }
28540
28541 case 's':
28542
28543 obj = Fget_buffer_process (Fcurrent_buffer ());
28544 if (NILP (obj))
28545 return "no process";
28546 #ifndef MSDOS
28547 obj = Fsymbol_name (Fprocess_status (obj));
28548 #endif
28549 break;
28550
28551 case '@':
28552 {
28553 specpdl_ref count = inhibit_garbage_collection ();
28554 Lisp_Object curdir = BVAR (current_buffer, directory);
28555 Lisp_Object val = Qnil;
28556
28557 if (STRINGP (curdir))
28558 val = safe_call1 (intern ("file-remote-p"), curdir);
28559
28560 val = unbind_to (count, val);
28561
28562 if (NILP (val))
28563 return "-";
28564 else
28565 return "@";
28566 }
28567
28568 case 'z':
28569
28570 case 'Z':
28571
28572 {
28573 bool eol_flag = (c == 'Z');
28574 char *p = decode_mode_spec_buf;
28575
28576 if (! FRAME_WINDOW_P (f))
28577 {
28578
28579
28580 p = decode_mode_spec_coding (CODING_ID_NAME
28581 (FRAME_KEYBOARD_CODING (f)->id),
28582 p, false);
28583 p = decode_mode_spec_coding (CODING_ID_NAME
28584 (FRAME_TERMINAL_CODING (f)->id),
28585 p, false);
28586 }
28587 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28588 p, eol_flag);
28589
28590 #if false
28591 #ifdef subprocesses
28592 obj = Fget_buffer_process (Fcurrent_buffer ());
28593 if (PROCESSP (obj))
28594 {
28595 p = decode_mode_spec_coding
28596 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28597 p = decode_mode_spec_coding
28598 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28599 }
28600 #endif
28601 #endif
28602 *p = 0;
28603 return decode_mode_spec_buf;
28604 }
28605 }
28606
28607 if (STRINGP (obj))
28608 {
28609 *string = obj;
28610 return SSDATA (obj);
28611 }
28612 else
28613 return "";
28614 }
28615
28616
28617
28618
28619 ptrdiff_t
28620 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28621 {
28622 ptrdiff_t ignored;
28623 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28624 }
28625
28626
28627
28628
28629
28630
28631
28632
28633
28634
28635
28636 static ptrdiff_t
28637 display_count_lines (ptrdiff_t start_byte,
28638 ptrdiff_t limit_byte, ptrdiff_t count,
28639 ptrdiff_t *byte_pos_ptr)
28640 {
28641 register unsigned char *cursor;
28642 unsigned char *base;
28643
28644 register ptrdiff_t ceiling;
28645 register unsigned char *ceiling_addr;
28646 ptrdiff_t orig_count = count;
28647
28648
28649
28650 bool selective_display
28651 = (!NILP (BVAR (current_buffer, selective_display))
28652 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28653
28654 if (count > 0)
28655 {
28656 while (start_byte < limit_byte)
28657 {
28658 ceiling = BUFFER_CEILING_OF (start_byte);
28659 ceiling = min (limit_byte - 1, ceiling);
28660 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28661 base = (cursor = BYTE_POS_ADDR (start_byte));
28662
28663 do
28664 {
28665 if (selective_display)
28666 {
28667 while (*cursor != '\n' && *cursor != 015
28668 && ++cursor != ceiling_addr)
28669 continue;
28670 if (cursor == ceiling_addr)
28671 break;
28672 }
28673 else
28674 {
28675 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28676 if (! cursor)
28677 break;
28678 }
28679
28680 cursor++;
28681
28682 if (--count == 0)
28683 {
28684 start_byte += cursor - base;
28685 *byte_pos_ptr = start_byte;
28686 return orig_count;
28687 }
28688 }
28689 while (cursor < ceiling_addr);
28690
28691 start_byte += ceiling_addr - base;
28692 }
28693 }
28694 else
28695 {
28696 while (start_byte > limit_byte)
28697 {
28698 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28699 ceiling = max (limit_byte, ceiling);
28700 ceiling_addr = BYTE_POS_ADDR (ceiling);
28701 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28702 while (true)
28703 {
28704 if (selective_display)
28705 {
28706 while (--cursor >= ceiling_addr
28707 && *cursor != '\n' && *cursor != 015)
28708 continue;
28709 if (cursor < ceiling_addr)
28710 break;
28711 }
28712 else
28713 {
28714 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28715 if (! cursor)
28716 break;
28717 }
28718
28719 if (++count == 0)
28720 {
28721 start_byte += cursor - base + 1;
28722 *byte_pos_ptr = start_byte;
28723
28724
28725 return - orig_count - 1;
28726 }
28727 }
28728 start_byte += ceiling_addr - base;
28729 }
28730 }
28731
28732 *byte_pos_ptr = limit_byte;
28733
28734 if (count < 0)
28735 return - orig_count + count;
28736 return orig_count - count;
28737
28738 }
28739
28740
28741
28742
28743
28744
28745
28746
28747
28748
28749
28750
28751
28752
28753
28754
28755
28756
28757
28758
28759
28760
28761
28762
28763
28764
28765
28766
28767
28768
28769
28770
28771
28772
28773
28774
28775
28776
28777
28778
28779
28780
28781
28782
28783
28784 static int
28785 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28786 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28787 int field_width, int precision, int max_x, int multibyte)
28788 {
28789 int hpos_at_start = it->hpos;
28790 int saved_face_id = it->face_id;
28791 struct glyph_row *row = it->glyph_row;
28792 ptrdiff_t it_charpos;
28793
28794
28795
28796 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28797 start, precision, field_width, multibyte);
28798
28799 if (string && STRINGP (lisp_string))
28800
28801
28802 it->stop_charpos = it->end_charpos;
28803
28804
28805
28806 if (STRINGP (face_string))
28807 {
28808 ptrdiff_t endptr;
28809 struct face *face;
28810
28811 it->face_id
28812 = face_at_string_position (it->w, face_string, face_string_pos,
28813 0, &endptr, it->base_face_id, false, 0);
28814 face = FACE_FROM_ID (it->f, it->face_id);
28815 it->face_box_p = face->box != FACE_NO_BOX;
28816
28817
28818
28819
28820 if (NILP (lisp_string))
28821 {
28822 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28823 face_string);
28824 if (!NILP (display))
28825 {
28826 Lisp_Object min_width = plist_get (display, Qmin_width);
28827 if (!NILP (min_width))
28828 display_min_width (it, 0, face_string, min_width);
28829 }
28830 }
28831 }
28832
28833
28834
28835 if (max_x <= 0)
28836 max_x = it->last_visible_x;
28837 else
28838 max_x = min (max_x, it->last_visible_x);
28839
28840
28841
28842 if (it->current_x < it->first_visible_x)
28843 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28844 MOVE_TO_POS | MOVE_TO_X);
28845
28846 row->ascent = it->max_ascent;
28847 row->height = it->max_ascent + it->max_descent;
28848 row->phys_ascent = it->max_phys_ascent;
28849 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28850 row->extra_line_spacing = it->max_extra_line_spacing;
28851
28852 if (STRINGP (it->string))
28853 it_charpos = IT_STRING_CHARPOS (*it);
28854 else
28855 it_charpos = IT_CHARPOS (*it);
28856
28857
28858
28859 while (it->current_x < max_x)
28860 {
28861 int x_before, x, n_glyphs_before, i, nglyphs;
28862
28863
28864 if (!get_next_display_element (it))
28865 break;
28866
28867
28868 x_before = it->current_x;
28869 n_glyphs_before = row->used[TEXT_AREA];
28870 PRODUCE_GLYPHS (it);
28871
28872 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28873 i = 0;
28874 x = x_before;
28875 while (i < nglyphs)
28876 {
28877 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28878
28879 if (it->line_wrap != TRUNCATE
28880 && x + glyph->pixel_width > max_x)
28881 {
28882
28883 if (CHAR_GLYPH_PADDING_P (*glyph))
28884 {
28885
28886 if (row->reversed_p)
28887 unproduce_glyphs (it, row->used[TEXT_AREA]
28888 - n_glyphs_before);
28889 row->used[TEXT_AREA] = n_glyphs_before;
28890 it->current_x = x_before;
28891 }
28892 else
28893 {
28894 if (row->reversed_p)
28895 unproduce_glyphs (it, row->used[TEXT_AREA]
28896 - (n_glyphs_before + i));
28897 row->used[TEXT_AREA] = n_glyphs_before + i;
28898 it->current_x = x;
28899 }
28900 break;
28901 }
28902 else if (x + glyph->pixel_width >= it->first_visible_x)
28903 {
28904
28905 ++it->hpos;
28906 if (x < it->first_visible_x)
28907 row->x = x - it->first_visible_x;
28908 }
28909 else
28910 {
28911
28912
28913 emacs_abort ();
28914 }
28915
28916 row->ascent = max (row->ascent, it->max_ascent);
28917 row->height = max (row->height, it->max_ascent + it->max_descent);
28918 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28919 row->phys_height = max (row->phys_height,
28920 it->max_phys_ascent + it->max_phys_descent);
28921 row->extra_line_spacing = max (row->extra_line_spacing,
28922 it->max_extra_line_spacing);
28923 x += glyph->pixel_width;
28924 ++i;
28925 }
28926
28927
28928 if (i < nglyphs)
28929 break;
28930
28931
28932 if (ITERATOR_AT_END_OF_LINE_P (it))
28933 {
28934 it->continuation_lines_width = 0;
28935 break;
28936 }
28937
28938 set_iterator_to_next (it, true);
28939 if (STRINGP (it->string))
28940 it_charpos = IT_STRING_CHARPOS (*it);
28941 else
28942 it_charpos = IT_CHARPOS (*it);
28943
28944
28945 if (it->line_wrap == TRUNCATE
28946 && it->current_x >= it->last_visible_x)
28947 {
28948
28949
28950
28951
28952
28953
28954 if (it_charpos <= it->string_nchars)
28955 {
28956 if (!FRAME_WINDOW_P (it->f))
28957 {
28958 int ii, n;
28959
28960 if (it->current_x > it->last_visible_x)
28961 {
28962
28963
28964 bool mode_line_p = false;
28965
28966
28967
28968 if (row->mode_line_p)
28969 {
28970 struct window *w = it->w;
28971 if (row == MATRIX_MODE_LINE_ROW (w->desired_matrix))
28972 mode_line_p = true;
28973 }
28974 if (!row->reversed_p)
28975 {
28976 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
28977 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28978 break;
28979 }
28980 else
28981 {
28982 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
28983 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28984 break;
28985 unproduce_glyphs (it, ii + 1);
28986 ii = row->used[TEXT_AREA] - (ii + 1);
28987 }
28988 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
28989 {
28990 row->used[TEXT_AREA] = ii;
28991 if (row->mode_line_p)
28992 pad_mode_line (it, mode_line_p);
28993 else
28994 produce_special_glyphs (it, IT_TRUNCATION);
28995 }
28996 }
28997 produce_special_glyphs (it, IT_TRUNCATION);
28998 }
28999 row->truncated_on_right_p = true;
29000 }
29001 break;
29002 }
29003 }
29004
29005
29006 if (it->first_visible_x
29007 && it_charpos > 0)
29008 {
29009 if (!FRAME_WINDOW_P (it->f)
29010 || (row->reversed_p
29011 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29012 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
29013 insert_left_trunc_glyphs (it);
29014 row->truncated_on_left_p = true;
29015 }
29016
29017 it->face_id = saved_face_id;
29018
29019
29020 return it->hpos - hpos_at_start;
29021 }
29022
29023
29024
29025
29026
29027
29028
29029
29030
29031
29032
29033 int
29034 invisible_prop (Lisp_Object propval, Lisp_Object list)
29035 {
29036 Lisp_Object tail, proptail;
29037
29038 for (tail = list; CONSP (tail); tail = XCDR (tail))
29039 {
29040 register Lisp_Object tem;
29041 tem = XCAR (tail);
29042 if (EQ (propval, tem))
29043 return 1;
29044 if (CONSP (tem) && EQ (propval, XCAR (tem)))
29045 return NILP (XCDR (tem)) ? 1 : 2;
29046 }
29047
29048 if (CONSP (propval))
29049 {
29050 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
29051 {
29052 Lisp_Object propelt;
29053 propelt = XCAR (proptail);
29054 for (tail = list; CONSP (tail); tail = XCDR (tail))
29055 {
29056 register Lisp_Object tem;
29057 tem = XCAR (tail);
29058 if (EQ (propelt, tem))
29059 return 1;
29060 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
29061 return NILP (XCDR (tem)) ? 1 : 2;
29062 }
29063 }
29064 }
29065
29066 return 0;
29067 }
29068
29069 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
29070 doc:
29071
29072
29073
29074
29075
29076
29077
29078
29079
29080
29081
29082 )
29083 (Lisp_Object pos)
29084 {
29085 Lisp_Object prop
29086 = (FIXNATP (pos) || MARKERP (pos)
29087 ? Fget_char_property (pos, Qinvisible, Qnil)
29088 : pos);
29089 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
29090 return (invis == 0 ? Qnil
29091 : invis == 1 ? Qt
29092 : make_fixnum (invis));
29093 }
29094
29095
29096
29097
29098
29099
29100
29101
29102
29103
29104
29105
29106
29107
29108
29109
29110
29111
29112
29113
29114
29115
29116
29117
29118
29119
29120
29121
29122
29123
29124
29125
29126
29127
29128
29129
29130
29131
29132
29133
29134
29135
29136
29137
29138
29139
29140
29141
29142
29143
29144
29145
29146
29147
29148
29149
29150
29151
29152
29153
29154
29155
29156
29157
29158
29159
29160
29161
29162
29163
29164
29165
29166
29167
29168
29169
29170
29171
29172
29173
29174
29175 static bool
29176 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
29177 struct font *font, bool width_p, int *align_to)
29178 {
29179
29180
29181
29182
29183 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
29184 double pixels;
29185
29186 # define OK_PIXELS(val) (*res = (val), true)
29187 # define OK_ALIGN_TO(val) (*align_to = (val), true)
29188
29189 if (NILP (prop))
29190 return OK_PIXELS (0);
29191
29192 eassert (FRAME_LIVE_P (it->f));
29193
29194 if (SYMBOLP (prop))
29195 {
29196 if (SCHARS (SYMBOL_NAME (prop)) == 2)
29197 {
29198 char *unit = SSDATA (SYMBOL_NAME (prop));
29199
29200
29201 if (unit[0] == 'i' && unit[1] == 'n')
29202 pixels = 1.0;
29203 else if (unit[0] == 'm' && unit[1] == 'm')
29204 pixels = 25.4;
29205 else if (unit[0] == 'c' && unit[1] == 'm')
29206 pixels = 2.54;
29207 else
29208 pixels = 0;
29209 if (pixels > 0)
29210 {
29211 double ppi = (width_p ? FRAME_RES_X (it->f)
29212 : FRAME_RES_Y (it->f));
29213
29214 if (ppi > 0)
29215 return OK_PIXELS (ppi / pixels);
29216 return false;
29217 }
29218 }
29219
29220 #ifdef HAVE_WINDOW_SYSTEM
29221
29222 if (EQ (prop, Qheight))
29223 return OK_PIXELS (font
29224 ? normal_char_height (font, -1)
29225 : FRAME_LINE_HEIGHT (it->f));
29226
29227 if (EQ (prop, Qwidth))
29228 return OK_PIXELS (font
29229 ? FONT_WIDTH (font)
29230 : FRAME_COLUMN_WIDTH (it->f));
29231 #else
29232 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
29233 return OK_PIXELS (1);
29234 #endif
29235
29236
29237 if (EQ (prop, Qtext))
29238 return OK_PIXELS (width_p
29239 ? (window_box_width (it->w, TEXT_AREA)
29240 - lnum_pixel_width)
29241 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
29242
29243
29244
29245
29246 if (align_to && *align_to < 0)
29247 {
29248 *res = 0;
29249
29250 if (EQ (prop, Qleft))
29251 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29252 + lnum_pixel_width);
29253
29254 if (EQ (prop, Qright))
29255 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
29256
29257 if (EQ (prop, Qcenter))
29258 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29259 + lnum_pixel_width
29260 + window_box_width (it->w, TEXT_AREA) / 2);
29261
29262 if (EQ (prop, Qleft_fringe))
29263 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29264 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29265 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29266
29267 if (EQ (prop, Qright_fringe))
29268 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29269 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29270 : window_box_right_offset (it->w, TEXT_AREA));
29271
29272 if (EQ (prop, Qleft_margin))
29273 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29274
29275 if (EQ (prop, Qright_margin))
29276 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29277
29278 if (EQ (prop, Qscroll_bar))
29279 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29280 ? 0
29281 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29282 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29283 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29284 : 0)));
29285 }
29286 else
29287 {
29288
29289 if (EQ (prop, Qleft_fringe))
29290 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29291 if (EQ (prop, Qright_fringe))
29292 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29293 if (EQ (prop, Qleft_margin))
29294 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29295 if (EQ (prop, Qright_margin))
29296 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29297 if (EQ (prop, Qscroll_bar))
29298 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29299 }
29300
29301 prop = buffer_local_value (prop, it->w->contents);
29302 if (BASE_EQ (prop, Qunbound))
29303 prop = Qnil;
29304 }
29305
29306 if (NUMBERP (prop))
29307 {
29308 int base_unit = (width_p
29309 ? FRAME_COLUMN_WIDTH (it->f)
29310 : FRAME_LINE_HEIGHT (it->f));
29311 if (width_p && align_to && *align_to < 0)
29312 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29313 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29314 }
29315
29316 if (CONSP (prop))
29317 {
29318 Lisp_Object car = XCAR (prop);
29319 Lisp_Object cdr = XCDR (prop);
29320
29321 if (SYMBOLP (car))
29322 {
29323 #ifdef HAVE_WINDOW_SYSTEM
29324
29325 if (FRAME_WINDOW_P (it->f)
29326 && valid_image_p (prop))
29327 {
29328 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29329 struct image *img = IMAGE_FROM_ID (it->f, id);
29330
29331 return OK_PIXELS (width_p ? img->width : img->height);
29332 }
29333
29334 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29335 {
29336
29337 return OK_PIXELS (100);
29338 }
29339 #endif
29340
29341
29342 if (EQ (car, Qplus) || EQ (car, Qminus))
29343 {
29344 bool first = true;
29345 double px;
29346
29347 pixels = 0;
29348 while (CONSP (cdr))
29349 {
29350 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29351 font, width_p, align_to))
29352 return false;
29353 if (first)
29354 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29355 else
29356 pixels += px;
29357 cdr = XCDR (cdr);
29358 }
29359 if (EQ (car, Qminus))
29360 pixels = -pixels;
29361 return OK_PIXELS (pixels);
29362 }
29363
29364 car = buffer_local_value (car, it->w->contents);
29365 if (BASE_EQ (car, Qunbound))
29366 car = Qnil;
29367 }
29368
29369
29370 if (NUMBERP (car))
29371 {
29372 double fact;
29373 int offset =
29374 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29375 pixels = XFLOATINT (car);
29376 if (NILP (cdr))
29377 return OK_PIXELS (pixels + offset);
29378 if (calc_pixel_width_or_height (&fact, it, cdr,
29379 font, width_p, align_to))
29380 return OK_PIXELS (pixels * fact + offset);
29381 return false;
29382 }
29383
29384 return false;
29385 }
29386
29387 return false;
29388 }
29389
29390 void
29391 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29392 {
29393 #ifdef HAVE_WINDOW_SYSTEM
29394 normal_char_ascent_descent (font, -1, ascent, descent);
29395 #else
29396 *ascent = 1;
29397 *descent = 0;
29398 #endif
29399 }
29400
29401
29402
29403
29404
29405
29406 #ifdef HAVE_WINDOW_SYSTEM
29407
29408 #ifdef GLYPH_DEBUG
29409
29410 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29411 void
29412 dump_glyph_string (struct glyph_string *s)
29413 {
29414 fputs ("glyph string\n", stderr);
29415 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29416 s->x, s->y, s->width, s->height);
29417 fprintf (stderr, " ybase = %d\n", s->ybase);
29418 fprintf (stderr, " hl = %u\n", s->hl);
29419 fprintf (stderr, " left overhang = %d, right = %d\n",
29420 s->left_overhang, s->right_overhang);
29421 fprintf (stderr, " nchars = %d\n", s->nchars);
29422 fprintf (stderr, " extends to end of line = %d\n",
29423 s->extends_to_end_of_line_p);
29424 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29425 fprintf (stderr, " bg width = %d\n", s->background_width);
29426 }
29427
29428 #endif
29429
29430
29431
29432
29433
29434
29435
29436
29437
29438 #ifdef HAVE_NTGUI
29439
29440
29441
29442
29443
29444 # define ALLOCATE_HDC(hdc, f) \
29445 Lisp_Object prev_quit = Vinhibit_quit; \
29446 Vinhibit_quit = Qt; \
29447 HDC hdc = get_frame_dc ((f))
29448 # define RELEASE_HDC(hdc, f) \
29449 release_frame_dc ((f), (hdc)); \
29450 Vinhibit_quit = prev_quit
29451 #else
29452 # define ALLOCATE_HDC(hdc, f)
29453 # define RELEASE_HDC(hdc, f)
29454 #endif
29455
29456 static void
29457 init_glyph_string (struct glyph_string *s,
29458 #ifdef HAVE_NTGUI
29459 HDC hdc,
29460 #endif
29461 unsigned *char2b, struct window *w, struct glyph_row *row,
29462 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29463 {
29464 memset (s, 0, sizeof *s);
29465 s->w = w;
29466 s->f = XFRAME (w->frame);
29467 #ifdef HAVE_NTGUI
29468 s->hdc = hdc;
29469 #endif
29470 s->char2b = char2b;
29471 s->hl = hl;
29472 s->row = row;
29473 s->area = area;
29474 s->first_glyph = row->glyphs[area] + start;
29475 s->height = row->height;
29476 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29477 s->ybase = s->y + row->ascent;
29478 }
29479
29480
29481
29482
29483
29484 static void
29485 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29486 struct glyph_string *h, struct glyph_string *t)
29487 {
29488 if (h)
29489 {
29490 if (*head)
29491 (*tail)->next = h;
29492 else
29493 *head = h;
29494 h->prev = *tail;
29495 *tail = t;
29496 }
29497 }
29498
29499
29500
29501
29502
29503
29504 static void
29505 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29506 struct glyph_string *h, struct glyph_string *t)
29507 {
29508 if (h)
29509 {
29510 if (*head)
29511 (*head)->prev = t;
29512 else
29513 *tail = t;
29514 t->next = *head;
29515 *head = h;
29516 }
29517 }
29518
29519
29520
29521
29522
29523 static void
29524 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29525 struct glyph_string *s)
29526 {
29527 s->next = s->prev = NULL;
29528 append_glyph_string_lists (head, tail, s, s);
29529 }
29530
29531
29532
29533
29534
29535
29536
29537
29538 static struct face *
29539 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29540 unsigned *char2b, bool display_p)
29541 {
29542 struct face *face = FACE_FROM_ID (f, face_id);
29543 unsigned code = 0;
29544
29545 if (face->font)
29546 {
29547 code = face->font->driver->encode_char (face->font, c);
29548
29549 if (code == FONT_INVALID_CODE)
29550 code = 0;
29551 }
29552
29553 *char2b = code & 0xFFFF;
29554
29555
29556 #ifdef HAVE_X_WINDOWS
29557 if (display_p)
29558 #endif
29559 {
29560 eassert (face != NULL);
29561 prepare_face_for_display (f, face);
29562 }
29563
29564 return face;
29565 }
29566
29567
29568
29569
29570
29571
29572 static struct face *
29573 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29574 unsigned *char2b)
29575 {
29576 struct face *face;
29577 unsigned code = 0;
29578
29579 eassert (glyph->type == CHAR_GLYPH);
29580 face = FACE_FROM_ID (f, glyph->face_id);
29581
29582
29583 prepare_face_for_display (f, face);
29584
29585 if (face->font)
29586 {
29587 if (CHAR_BYTE8_P (glyph->u.ch))
29588 code = CHAR_TO_BYTE8 (glyph->u.ch);
29589 else
29590 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29591
29592 if (code == FONT_INVALID_CODE)
29593 code = 0;
29594 }
29595
29596
29597 *char2b = code & 0xFFFF;
29598 return face;
29599 }
29600
29601
29602
29603
29604
29605 static bool
29606 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29607 {
29608 unsigned code;
29609
29610 if (CHAR_BYTE8_P (c))
29611 code = CHAR_TO_BYTE8 (c);
29612 else
29613 code = font->driver->encode_char (font, c);
29614
29615 if (code == FONT_INVALID_CODE)
29616 return false;
29617
29618
29619 *char2b = code & 0xFFFF;
29620 return true;
29621 }
29622
29623
29624
29625
29626
29627
29628
29629
29630
29631
29632
29633
29634 static int
29635 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29636 int overlaps)
29637 {
29638 int i;
29639
29640
29641
29642 struct face *face;
29643
29644 eassert (s);
29645
29646 s->for_overlaps = overlaps;
29647 s->face = NULL;
29648 s->font = NULL;
29649 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29650 {
29651 int c = COMPOSITION_GLYPH (s->cmp, i);
29652
29653
29654
29655 if (c != '\t')
29656 {
29657 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29658 -1, Qnil);
29659
29660 face = get_char_face_and_encoding (s->f, c, face_id,
29661 s->char2b + i, true);
29662 if (face)
29663 {
29664 if (! s->face)
29665 {
29666 s->face = face;
29667 s->font = s->face->font;
29668 }
29669 else if (s->face != face)
29670 break;
29671 }
29672 }
29673 ++s->nchars;
29674 }
29675 s->cmp_to = i;
29676
29677 if (s->face == NULL)
29678 {
29679 s->face = base_face->ascii_face;
29680 s->font = s->face->font;
29681 }
29682
29683 if (s->hl == DRAW_MOUSE_FACE
29684 || (s->hl == DRAW_CURSOR
29685 && MATRIX_ROW (s->w->current_matrix,
29686 s->w->phys_cursor.vpos)->mouse_face_p
29687 && cursor_in_mouse_face_p (s->w)))
29688 {
29689 int c = COMPOSITION_GLYPH (s->cmp, 0);
29690 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29691 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29692 if (!s->face)
29693 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29694
29695 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29696 prepare_face_for_display (s->f, s->face);
29697 }
29698
29699
29700
29701 s->width = s->first_glyph->pixel_width;
29702
29703
29704
29705
29706
29707 if (s->font == NULL)
29708 {
29709 s->font_not_found_p = true;
29710 s->font = FRAME_FONT (s->f);
29711 }
29712
29713
29714 s->ybase += s->first_glyph->voffset;
29715
29716 return s->cmp_to;
29717 }
29718
29719 static int
29720 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29721 int start, int end, int overlaps)
29722 {
29723 struct glyph *glyph, *last;
29724 int voffset;
29725 Lisp_Object lgstring;
29726 int i;
29727 bool glyph_not_available_p;
29728
29729 s->for_overlaps = overlaps;
29730 glyph = s->row->glyphs[s->area] + start;
29731 last = s->row->glyphs[s->area] + end;
29732 voffset = glyph->voffset;
29733 glyph_not_available_p = glyph->glyph_not_available_p;
29734 s->cmp_id = glyph->u.cmp.id;
29735 s->cmp_from = glyph->slice.cmp.from;
29736 s->cmp_to = glyph->slice.cmp.to + 1;
29737 if (s->hl == DRAW_MOUSE_FACE
29738 || (s->hl == DRAW_CURSOR
29739 && MATRIX_ROW (s->w->current_matrix,
29740 s->w->phys_cursor.vpos)->mouse_face_p
29741 && cursor_in_mouse_face_p (s->w)))
29742 {
29743 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29744 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29745 if (!s->face)
29746 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29747 prepare_face_for_display (s->f, s->face);
29748 }
29749 else
29750 s->face = FACE_FROM_ID (s->f, face_id);
29751 lgstring = composition_gstring_from_id (s->cmp_id);
29752 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29753
29754
29755 s->width = s->first_glyph->pixel_width;
29756 glyph++;
29757 while (glyph < last
29758 && glyph->u.cmp.automatic
29759 && glyph->u.cmp.id == s->cmp_id
29760 && glyph->face_id == face_id
29761 && s->cmp_to == glyph->slice.cmp.from
29762 && glyph->glyph_not_available_p == glyph_not_available_p)
29763 {
29764 s->width += glyph->pixel_width;
29765 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29766 }
29767
29768 for (i = s->cmp_from; i < s->cmp_to; i++)
29769 {
29770 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29771 unsigned code = LGLYPH_CODE (lglyph);
29772
29773
29774 s->char2b[i] = code & 0xFFFF;
29775 }
29776
29777
29778
29779
29780 if (glyph_not_available_p)
29781 s->font_not_found_p = true;
29782
29783
29784 s->ybase += voffset;
29785
29786 return glyph - s->row->glyphs[s->area];
29787 }
29788
29789
29790
29791
29792
29793
29794
29795 static int
29796 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29797 int start, int end, int overlaps)
29798 {
29799 struct glyph *glyph, *last;
29800 int voffset;
29801
29802 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29803 s->for_overlaps = overlaps;
29804 glyph = s->row->glyphs[s->area] + start;
29805 last = s->row->glyphs[s->area] + end;
29806 voffset = glyph->voffset;
29807 s->face = FACE_FROM_ID (s->f, face_id);
29808 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29809 if (s->hl == DRAW_MOUSE_FACE
29810 || (s->hl == DRAW_CURSOR
29811 && MATRIX_ROW (s->w->current_matrix,
29812 s->w->phys_cursor.vpos)->mouse_face_p
29813 && cursor_in_mouse_face_p (s->w)))
29814 {
29815 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29816 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29817 if (!s->face)
29818 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29819 prepare_face_for_display (s->f, s->face);
29820 }
29821 s->nchars = 1;
29822 s->width = glyph->pixel_width;
29823 glyph++;
29824 while (glyph < last
29825 && glyph->type == GLYPHLESS_GLYPH
29826 && glyph->voffset == voffset
29827 && glyph->face_id == face_id)
29828 {
29829 s->nchars++;
29830 s->width += glyph->pixel_width;
29831 glyph++;
29832 }
29833 s->ybase += voffset;
29834 return glyph - s->row->glyphs[s->area];
29835 }
29836
29837
29838
29839
29840
29841
29842
29843
29844
29845
29846
29847 static int
29848 fill_glyph_string (struct glyph_string *s, int face_id,
29849 int start, int end, int overlaps)
29850 {
29851 struct glyph *glyph, *last;
29852 int voffset;
29853 bool glyph_not_available_p;
29854
29855 eassert (s->f == XFRAME (s->w->frame));
29856 eassert (s->nchars == 0);
29857 eassert (start >= 0 && end > start);
29858
29859 s->for_overlaps = overlaps;
29860 glyph = s->row->glyphs[s->area] + start;
29861 last = s->row->glyphs[s->area] + end;
29862 voffset = glyph->voffset;
29863 s->padding_p = glyph->padding_p;
29864 glyph_not_available_p = glyph->glyph_not_available_p;
29865
29866 while (glyph < last
29867 && glyph->type == CHAR_GLYPH
29868 && glyph->voffset == voffset
29869
29870 && glyph->face_id == face_id
29871 && glyph->glyph_not_available_p == glyph_not_available_p)
29872 {
29873 s->face = get_glyph_face_and_encoding (s->f, glyph,
29874 s->char2b + s->nchars);
29875 ++s->nchars;
29876 eassert (s->nchars <= end - start);
29877 s->width += glyph->pixel_width;
29878 if (glyph++->padding_p != s->padding_p)
29879 break;
29880 }
29881
29882 s->font = s->face->font;
29883
29884 if (s->hl == DRAW_MOUSE_FACE
29885 || (s->hl == DRAW_CURSOR
29886 && MATRIX_ROW (s->w->current_matrix,
29887 s->w->phys_cursor.vpos)->mouse_face_p
29888 && cursor_in_mouse_face_p (s->w)))
29889 {
29890 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29891 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29892 if (!s->face)
29893 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29894 s->face
29895 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29896 s->first_glyph->u.ch, -1, Qnil));
29897 prepare_face_for_display (s->f, s->face);
29898 }
29899
29900
29901
29902
29903
29904 if (s->font == NULL || glyph_not_available_p)
29905 {
29906 s->font_not_found_p = true;
29907 s->font = FRAME_FONT (s->f);
29908 }
29909
29910
29911 s->ybase += voffset;
29912
29913 eassert (s->face && s->face->gc);
29914 return glyph - s->row->glyphs[s->area];
29915 }
29916
29917
29918
29919
29920 static void
29921 fill_image_glyph_string (struct glyph_string *s)
29922 {
29923 eassert (s->first_glyph->type == IMAGE_GLYPH);
29924 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29925 eassert (s->img);
29926 s->slice = s->first_glyph->slice.img;
29927 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29928 s->font = s->face->font;
29929 if (s->hl == DRAW_MOUSE_FACE
29930 || (s->hl == DRAW_CURSOR
29931 && MATRIX_ROW (s->w->current_matrix,
29932 s->w->phys_cursor.vpos)->mouse_face_p
29933 && cursor_in_mouse_face_p (s->w)))
29934 {
29935 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29936 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29937 if (!s->face)
29938 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29939 prepare_face_for_display (s->f, s->face);
29940 }
29941 s->width = s->first_glyph->pixel_width;
29942
29943
29944 s->ybase += s->first_glyph->voffset;
29945 }
29946
29947
29948 #ifdef HAVE_XWIDGETS
29949 static void
29950 fill_xwidget_glyph_string (struct glyph_string *s)
29951 {
29952 eassert (s->first_glyph->type == XWIDGET_GLYPH);
29953 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29954 s->font = s->face->font;
29955 if (s->hl == DRAW_MOUSE_FACE
29956 || (s->hl == DRAW_CURSOR
29957 && MATRIX_ROW (s->w->current_matrix,
29958 s->w->phys_cursor.vpos)->mouse_face_p
29959 && cursor_in_mouse_face_p (s->w)))
29960 {
29961 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29962 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29963 if (!s->face)
29964 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29965 prepare_face_for_display (s->f, s->face);
29966 }
29967 s->width = s->first_glyph->pixel_width;
29968 s->ybase += s->first_glyph->voffset;
29969 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
29970 }
29971 #endif
29972
29973
29974
29975
29976
29977
29978
29979 static int
29980 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
29981 {
29982 struct glyph *glyph, *last;
29983 int voffset, face_id;
29984
29985 eassert (s->first_glyph->type == STRETCH_GLYPH);
29986
29987 glyph = s->row->glyphs[s->area] + start;
29988 last = s->row->glyphs[s->area] + end;
29989 face_id = glyph->face_id;
29990 s->face = FACE_FROM_ID (s->f, face_id);
29991 s->font = s->face->font;
29992 if (s->hl == DRAW_MOUSE_FACE
29993 || (s->hl == DRAW_CURSOR
29994 && MATRIX_ROW (s->w->current_matrix,
29995 s->w->phys_cursor.vpos)->mouse_face_p
29996 && cursor_in_mouse_face_p (s->w)))
29997 {
29998 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29999 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
30000 if (!s->face)
30001 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30002 prepare_face_for_display (s->f, s->face);
30003 }
30004 s->width = glyph->pixel_width;
30005 s->nchars = 1;
30006 voffset = glyph->voffset;
30007
30008 for (++glyph;
30009 (glyph < last
30010 && glyph->type == STRETCH_GLYPH
30011 && glyph->voffset == voffset
30012 && glyph->face_id == face_id);
30013 ++glyph)
30014 s->width += glyph->pixel_width;
30015
30016
30017 s->ybase += voffset;
30018
30019
30020
30021 eassert (s->face);
30022 return glyph - s->row->glyphs[s->area];
30023 }
30024
30025 static struct font_metrics *
30026 get_per_char_metric (struct font *font, const unsigned *char2b)
30027 {
30028 static struct font_metrics metrics;
30029
30030 if (! font)
30031 return NULL;
30032 if (*char2b == FONT_INVALID_CODE)
30033 return NULL;
30034
30035 font->driver->text_extents (font, char2b, 1, &metrics);
30036 return &metrics;
30037 }
30038
30039
30040
30041
30042
30043
30044
30045 static void
30046 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
30047 {
30048 *ascent = FONT_BASE (font);
30049 *descent = FONT_DESCENT (font);
30050
30051 if (FONT_TOO_HIGH (font))
30052 {
30053 unsigned char2b;
30054
30055
30056
30057 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
30058 {
30059 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
30060 eassume (pcm);
30061
30062 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
30063 {
30064
30065
30066
30067 *ascent = pcm->ascent + 1;
30068 *descent = pcm->descent + 1;
30069 }
30070 }
30071 }
30072 }
30073
30074
30075
30076
30077
30078
30079 static int
30080 normal_char_height (struct font *font, int c)
30081 {
30082 int ascent, descent;
30083
30084 normal_char_ascent_descent (font, c, &ascent, &descent);
30085
30086 return ascent + descent;
30087 }
30088
30089
30090
30091
30092
30093
30094 void
30095 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
30096 {
30097 *left = *right = 0;
30098
30099 if (glyph->type == CHAR_GLYPH)
30100 {
30101 unsigned char2b;
30102 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
30103 if (face->font)
30104 {
30105 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
30106 if (pcm)
30107 {
30108 if (pcm->rbearing > pcm->width)
30109 *right = pcm->rbearing - pcm->width;
30110 if (pcm->lbearing < 0)
30111 *left = -pcm->lbearing;
30112 }
30113 }
30114 }
30115 else if (glyph->type == COMPOSITE_GLYPH)
30116 {
30117 if (! glyph->u.cmp.automatic)
30118 {
30119 struct composition *cmp = composition_table[glyph->u.cmp.id];
30120
30121 if (cmp->rbearing > cmp->pixel_width)
30122 *right = cmp->rbearing - cmp->pixel_width;
30123 if (cmp->lbearing < 0)
30124 *left = - cmp->lbearing;
30125 }
30126 else
30127 {
30128 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
30129 struct font_metrics metrics;
30130
30131 composition_gstring_width (gstring, glyph->slice.cmp.from,
30132 glyph->slice.cmp.to + 1, &metrics);
30133 if (metrics.rbearing > metrics.width)
30134 *right = metrics.rbearing - metrics.width;
30135 if (metrics.lbearing < 0)
30136 *left = - metrics.lbearing;
30137 }
30138 }
30139 }
30140
30141
30142
30143
30144
30145
30146 static int
30147 left_overwritten (struct glyph_string *s)
30148 {
30149 int k;
30150
30151 if (s->left_overhang)
30152 {
30153 int x = 0, i;
30154 struct glyph *glyphs = s->row->glyphs[s->area];
30155 int first = s->first_glyph - glyphs;
30156
30157 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
30158 x -= glyphs[i].pixel_width;
30159
30160 k = i + 1;
30161 }
30162 else
30163 k = -1;
30164
30165 return k;
30166 }
30167
30168
30169
30170
30171
30172
30173 static int
30174 left_overwriting (struct glyph_string *s)
30175 {
30176 int i, k, x;
30177 struct glyph *glyphs = s->row->glyphs[s->area];
30178 int first = s->first_glyph - glyphs;
30179
30180 k = -1;
30181 x = 0;
30182 for (i = first - 1; i >= 0; --i)
30183 {
30184 int left, right;
30185 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30186 if (x + right > 0)
30187 k = i;
30188 x -= glyphs[i].pixel_width;
30189 }
30190
30191 return k;
30192 }
30193
30194
30195
30196
30197
30198
30199 static int
30200 right_overwritten (struct glyph_string *s)
30201 {
30202 int k = -1;
30203
30204 if (s->right_overhang)
30205 {
30206 int x = 0, i;
30207 struct glyph *glyphs = s->row->glyphs[s->area];
30208 int first = (s->first_glyph - glyphs
30209 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30210 int end = s->row->used[s->area];
30211
30212 for (i = first; i < end && s->right_overhang > x; ++i)
30213 x += glyphs[i].pixel_width;
30214
30215 k = i;
30216 }
30217
30218 return k;
30219 }
30220
30221
30222
30223
30224
30225
30226 static int
30227 right_overwriting (struct glyph_string *s)
30228 {
30229 int i, k, x;
30230 int end = s->row->used[s->area];
30231 struct glyph *glyphs = s->row->glyphs[s->area];
30232 int first = (s->first_glyph - glyphs
30233 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30234
30235 k = -1;
30236 x = 0;
30237 for (i = first; i < end; ++i)
30238 {
30239 int left, right;
30240 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30241 if (x - left < 0)
30242 k = i;
30243 x += glyphs[i].pixel_width;
30244 }
30245
30246 return k;
30247 }
30248
30249
30250
30251
30252
30253
30254
30255
30256
30257
30258
30259 static void
30260 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30261 {
30262
30263
30264
30265 if (start == s->row->used[s->area]
30266 && ((s->row->fill_line_p
30267 && (s->hl == DRAW_NORMAL_TEXT
30268 || s->hl == DRAW_IMAGE_RAISED
30269 || s->hl == DRAW_IMAGE_SUNKEN))
30270 || s->hl == DRAW_MOUSE_FACE))
30271 s->extends_to_end_of_line_p = true;
30272
30273
30274
30275
30276 if (s->extends_to_end_of_line_p)
30277 s->background_width = last_x - s->x + 1;
30278 else
30279 {
30280 s->background_width = s->width;
30281 #ifdef HAVE_WINDOW_SYSTEM
30282 if (FRAME_WINDOW_P (s->f)
30283 && s->hl == DRAW_CURSOR
30284 && MATRIX_ROW (s->w->current_matrix,
30285 s->w->phys_cursor.vpos)->mouse_face_p
30286 && cursor_in_mouse_face_p (s->w))
30287 {
30288
30289
30290
30291
30292 struct glyph *g = s->first_glyph;
30293 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30294 s->background_width +=
30295 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30296 regular_face, s->face);
30297
30298 s->width = s->background_width;
30299 }
30300 #endif
30301 }
30302 }
30303
30304
30305
30306
30307
30308 static struct glyph_string *
30309 glyph_string_containing_background_width (struct glyph_string *s)
30310 {
30311 if (s->cmp)
30312 while (s->cmp_from)
30313 s = s->prev;
30314
30315 return s;
30316 }
30317
30318
30319
30320
30321
30322
30323 static void
30324 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30325 {
30326 if (backward_p)
30327 {
30328 while (s)
30329 {
30330 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30331 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30332 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30333 x -= s->width;
30334 s->x = x;
30335 s = s->prev;
30336 }
30337 }
30338 else
30339 {
30340 while (s)
30341 {
30342 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30343 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30344 s->x = x;
30345 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30346 x += s->width;
30347 s = s->next;
30348 }
30349 }
30350 }
30351
30352
30353
30354
30355
30356
30357
30358
30359
30360 #ifdef HAVE_NTGUI
30361
30362
30363 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30364 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30365 #else
30366 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30367 init_glyph_string (s, char2b, w, row, area, start, hl)
30368 #endif
30369
30370
30371
30372
30373
30374
30375
30376
30377
30378
30379
30380 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30381 do \
30382 { \
30383 s = alloca (sizeof *s); \
30384 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30385 START = fill_stretch_glyph_string (s, START, END); \
30386 append_glyph_string (&HEAD, &TAIL, s); \
30387 s->x = (X); \
30388 } \
30389 while (false)
30390
30391
30392
30393
30394
30395
30396
30397
30398
30399
30400 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30401 do \
30402 { \
30403 s = alloca (sizeof *s); \
30404 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30405 fill_image_glyph_string (s); \
30406 append_glyph_string (&HEAD, &TAIL, s); \
30407 ++START; \
30408 s->x = (X); \
30409 } \
30410 while (false)
30411
30412 #ifndef HAVE_XWIDGETS
30413 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30414 eassume (false)
30415 #else
30416 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30417 do \
30418 { \
30419 s = alloca (sizeof *s); \
30420 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30421 fill_xwidget_glyph_string (s); \
30422 append_glyph_string (&(HEAD), &(TAIL), s); \
30423 ++(START); \
30424 s->x = (X); \
30425 } \
30426 while (false)
30427 #endif
30428
30429
30430
30431
30432
30433
30434
30435
30436
30437
30438 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30439 do \
30440 { \
30441 int face_id; \
30442 unsigned *char2b; \
30443 \
30444 face_id = (row)->glyphs[area][START].face_id; \
30445 \
30446 s = alloca (sizeof *s); \
30447 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30448 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30449 append_glyph_string (&HEAD, &TAIL, s); \
30450 s->x = (X); \
30451 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30452 } \
30453 while (false)
30454
30455
30456
30457
30458
30459
30460
30461
30462
30463
30464
30465 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30466 do { \
30467 int face_id = (row)->glyphs[area][START].face_id; \
30468 struct face *base_face = FACE_FROM_ID (f, face_id); \
30469 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30470 struct composition *cmp = composition_table[cmp_id]; \
30471 unsigned *char2b; \
30472 struct glyph_string *first_s = NULL; \
30473 int n; \
30474 \
30475 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30476 \
30477
30478 \
30479 for (n = 0; n < cmp->glyph_len;) \
30480 { \
30481 s = alloca (sizeof *s); \
30482 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30483 append_glyph_string (&(HEAD), &(TAIL), s); \
30484 s->cmp = cmp; \
30485 s->cmp_from = n; \
30486 s->x = (X); \
30487 if (n == 0) \
30488 first_s = s; \
30489 n = fill_composite_glyph_string (s, base_face, overlaps); \
30490 } \
30491 \
30492 ++START; \
30493 s = first_s; \
30494 } while (false)
30495
30496
30497
30498
30499
30500 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30501 do { \
30502 int face_id; \
30503 unsigned *char2b; \
30504 Lisp_Object gstring; \
30505 \
30506 face_id = (row)->glyphs[area][START].face_id; \
30507 gstring = (composition_gstring_from_id \
30508 ((row)->glyphs[area][START].u.cmp.id)); \
30509 s = alloca (sizeof *s); \
30510 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30511 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30512 append_glyph_string (&(HEAD), &(TAIL), s); \
30513 s->x = (X); \
30514 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30515 } while (false)
30516
30517
30518
30519
30520
30521
30522 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30523 do \
30524 { \
30525 int face_id; \
30526 \
30527 face_id = (row)->glyphs[area][START].face_id; \
30528 \
30529 s = alloca (sizeof *s); \
30530 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30531 append_glyph_string (&HEAD, &TAIL, s); \
30532 s->x = (X); \
30533 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30534 overlaps); \
30535 } \
30536 while (false)
30537
30538
30539
30540
30541
30542
30543
30544
30545
30546
30547
30548
30549 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30550 do \
30551 { \
30552 HEAD = TAIL = NULL; \
30553 while (START < END) \
30554 { \
30555 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30556 switch (first_glyph->type) \
30557 { \
30558 case CHAR_GLYPH: \
30559 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30560 HL, X, LAST_X); \
30561 break; \
30562 \
30563 case COMPOSITE_GLYPH: \
30564 if (first_glyph->u.cmp.automatic) \
30565 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30566 HL, X, LAST_X); \
30567 else \
30568 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30569 HL, X, LAST_X); \
30570 break; \
30571 \
30572 case STRETCH_GLYPH: \
30573 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30574 HL, X, LAST_X); \
30575 break; \
30576 \
30577 case IMAGE_GLYPH: \
30578 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30579 HL, X, LAST_X); \
30580 break;
30581
30582 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30583 case XWIDGET_GLYPH: \
30584 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30585 HL, X, LAST_X); \
30586 break;
30587
30588 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30589 case GLYPHLESS_GLYPH: \
30590 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30591 HL, X, LAST_X); \
30592 break; \
30593 \
30594 default: \
30595 emacs_abort (); \
30596 } \
30597 \
30598 if (s) \
30599 { \
30600 set_glyph_string_background_width (s, START, LAST_X); \
30601 (X) += s->width; \
30602 } \
30603 } \
30604 } while (false)
30605
30606
30607 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30608 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30609 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30610 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30611
30612
30613
30614
30615
30616
30617
30618
30619
30620
30621
30622
30623
30624
30625
30626
30627
30628
30629
30630
30631
30632
30633
30634
30635 static int
30636 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30637 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30638 enum draw_glyphs_face hl, int overlaps)
30639 {
30640 struct glyph_string *head, *tail;
30641 struct glyph_string *s;
30642 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30643 int i, j, x_reached, last_x, area_left = 0;
30644 struct frame *f = XFRAME (WINDOW_FRAME (w));
30645
30646 ALLOCATE_HDC (hdc, f);
30647
30648
30649 end = min (end, row->used[area]);
30650 start = clip_to_bounds (0, start, end);
30651
30652
30653
30654 if (row->full_width_p)
30655 {
30656
30657
30658 area_left = WINDOW_LEFT_EDGE_X (w);
30659 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30660 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30661 }
30662 else
30663 {
30664 area_left = window_box_left (w, area);
30665 last_x = area_left + window_box_width (w, area);
30666 }
30667 x += area_left;
30668
30669
30670
30671
30672
30673 i = start;
30674 USE_SAFE_ALLOCA;
30675 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30676 if (tail)
30677 {
30678 s = glyph_string_containing_background_width (tail);
30679 x_reached = s->x + s->background_width;
30680 }
30681 else
30682 x_reached = x;
30683
30684
30685
30686
30687 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30688 {
30689 struct glyph_string *h, *t;
30690 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30691 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30692 bool check_mouse_face = false;
30693 int dummy_x = 0;
30694
30695
30696
30697 if (area == TEXT_AREA && row->mouse_face_p
30698 && hlinfo->mouse_face_beg_row >= 0
30699 && hlinfo->mouse_face_end_row >= 0)
30700 {
30701 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30702
30703 if (row_vpos >= hlinfo->mouse_face_beg_row
30704 && row_vpos <= hlinfo->mouse_face_end_row)
30705 {
30706 check_mouse_face = true;
30707 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30708 ? hlinfo->mouse_face_beg_col : 0;
30709 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30710 ? hlinfo->mouse_face_end_col
30711 : row->used[TEXT_AREA];
30712 }
30713 }
30714
30715
30716 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30717 for (s = head; s; s = s->next)
30718 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30719
30720
30721
30722
30723
30724
30725 i = left_overwritten (head);
30726 if (i >= 0)
30727 {
30728 enum draw_glyphs_face overlap_hl;
30729
30730
30731
30732
30733
30734
30735
30736
30737 if (check_mouse_face
30738 && mouse_beg_col < start && mouse_end_col > i)
30739 overlap_hl = DRAW_MOUSE_FACE;
30740 else
30741 overlap_hl = DRAW_NORMAL_TEXT;
30742
30743 if (hl != overlap_hl)
30744 clip_head = head;
30745 j = i;
30746 BUILD_GLYPH_STRINGS (j, start, h, t,
30747 overlap_hl, dummy_x, last_x);
30748 start = i;
30749 compute_overhangs_and_x (t, head->x, true);
30750 prepend_glyph_string_lists (&head, &tail, h, t);
30751 if (clip_head == NULL)
30752 clip_head = head;
30753 }
30754
30755
30756
30757
30758
30759
30760
30761
30762 i = left_overwriting (head);
30763 if (i >= 0)
30764 {
30765 enum draw_glyphs_face overlap_hl;
30766
30767 if (check_mouse_face
30768 && mouse_beg_col < start && mouse_end_col > i)
30769 overlap_hl = DRAW_MOUSE_FACE;
30770 else
30771 overlap_hl = DRAW_NORMAL_TEXT;
30772
30773 if (hl == overlap_hl || clip_head == NULL)
30774 clip_head = head;
30775 BUILD_GLYPH_STRINGS (i, start, h, t,
30776 overlap_hl, dummy_x, last_x);
30777 for (s = h; s; s = s->next)
30778 s->background_filled_p = true;
30779 compute_overhangs_and_x (t, head->x, true);
30780 prepend_glyph_string_lists (&head, &tail, h, t);
30781 }
30782
30783
30784
30785
30786
30787 i = right_overwritten (tail);
30788 if (i >= 0)
30789 {
30790 enum draw_glyphs_face overlap_hl;
30791
30792 if (check_mouse_face
30793 && mouse_beg_col < i && mouse_end_col > end)
30794 overlap_hl = DRAW_MOUSE_FACE;
30795 else
30796 overlap_hl = DRAW_NORMAL_TEXT;
30797
30798 if (hl != overlap_hl)
30799 clip_tail = tail;
30800 BUILD_GLYPH_STRINGS (end, i, h, t,
30801 overlap_hl, x, last_x);
30802
30803
30804 compute_overhangs_and_x (h, tail->x + tail->width, false);
30805 append_glyph_string_lists (&head, &tail, h, t);
30806 if (clip_tail == NULL)
30807 clip_tail = tail;
30808 }
30809
30810
30811
30812
30813
30814
30815 i = right_overwriting (tail);
30816 if (i >= 0)
30817 {
30818 enum draw_glyphs_face overlap_hl;
30819 if (check_mouse_face
30820 && mouse_beg_col < i && mouse_end_col > end)
30821 overlap_hl = DRAW_MOUSE_FACE;
30822 else
30823 overlap_hl = DRAW_NORMAL_TEXT;
30824
30825 if (hl == overlap_hl || clip_tail == NULL)
30826 clip_tail = tail;
30827 i++;
30828 BUILD_GLYPH_STRINGS (end, i, h, t,
30829 overlap_hl, x, last_x);
30830 for (s = h; s; s = s->next)
30831 s->background_filled_p = true;
30832 compute_overhangs_and_x (h, tail->x + tail->width, false);
30833 append_glyph_string_lists (&head, &tail, h, t);
30834 }
30835 tail = glyph_string_containing_background_width (tail);
30836 if (clip_tail)
30837 clip_tail = glyph_string_containing_background_width (clip_tail);
30838 if (clip_head || clip_tail)
30839 for (s = head; s; s = s->next)
30840 {
30841 s->clip_head = clip_head;
30842 s->clip_tail = clip_tail;
30843 }
30844 }
30845
30846
30847 for (s = head; s; s = s->next)
30848 FRAME_RIF (f)->draw_glyph_string (s);
30849
30850
30851
30852 if (area == TEXT_AREA
30853 && !row->full_width_p
30854
30855
30856
30857 && !overlaps)
30858 {
30859 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30860 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30861 : (tail ? tail->x + tail->background_width : x));
30862 x0 -= area_left;
30863 x1 -= area_left;
30864
30865 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30866 row->y, MATRIX_ROW_BOTTOM_Y (row));
30867 }
30868
30869
30870
30871 if (row->full_width_p)
30872 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30873 else
30874 x_reached -= area_left;
30875
30876 RELEASE_HDC (hdc, f);
30877
30878 SAFE_FREE ();
30879 return x_reached;
30880 }
30881
30882
30883
30884
30885
30886
30887
30888
30889 struct font *
30890 font_for_underline_metrics (struct glyph_string *s)
30891 {
30892 struct glyph *g0 = s->row->glyphs[s->area], *g;
30893
30894 for (g = s->first_glyph - 1; g >= g0; g--)
30895 {
30896 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30897 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30898 break;
30899 }
30900
30901
30902 if (g == s->first_glyph - 1)
30903 return s->font;
30904 else
30905 {
30906
30907
30908 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30909 }
30910 }
30911
30912
30913
30914
30915 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30916 { \
30917 if (!it->f->fonts_changed \
30918 && (it->glyph_row->glyphs[area] \
30919 < it->glyph_row->glyphs[area + 1])) \
30920 { \
30921 it->w->ncols_scale_factor++; \
30922 it->f->fonts_changed = true; \
30923 } \
30924 }
30925
30926
30927
30928
30929 static void
30930 append_glyph (struct it *it)
30931 {
30932 struct glyph *glyph;
30933 enum glyph_row_area area = it->area;
30934
30935 eassert (it->glyph_row);
30936 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
30937
30938 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30939 if (glyph < it->glyph_row->glyphs[area + 1])
30940 {
30941
30942
30943 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30944 {
30945 struct glyph *g;
30946
30947
30948 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
30949 g[1] = *g;
30950 glyph = it->glyph_row->glyphs[area];
30951 }
30952 glyph->charpos = CHARPOS (it->position);
30953 glyph->object = it->object;
30954 if (it->pixel_width > 0)
30955 {
30956 eassert (it->pixel_width <= SHRT_MAX);
30957 glyph->pixel_width = it->pixel_width;
30958 glyph->padding_p = false;
30959 }
30960 else
30961 {
30962
30963
30964 glyph->pixel_width = 1;
30965 glyph->padding_p = true;
30966 }
30967 glyph->ascent = it->ascent;
30968 glyph->descent = it->descent;
30969 glyph->voffset = it->voffset;
30970 glyph->type = CHAR_GLYPH;
30971 glyph->avoid_cursor_p = it->avoid_cursor_p;
30972 glyph->multibyte_p = it->multibyte_p;
30973 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30974 {
30975
30976
30977 glyph->right_box_line_p = it->start_of_box_run_p;
30978 glyph->left_box_line_p = it->end_of_box_run_p;
30979 }
30980 else
30981 {
30982 glyph->left_box_line_p = it->start_of_box_run_p;
30983 glyph->right_box_line_p = it->end_of_box_run_p;
30984 }
30985 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30986 || it->phys_descent > it->descent);
30987 glyph->glyph_not_available_p = it->glyph_not_available_p;
30988 glyph->face_id = it->face_id;
30989 glyph->u.ch = it->char_to_display;
30990 glyph->slice.img = null_glyph_slice;
30991 glyph->font_type = FONT_TYPE_UNKNOWN;
30992 if (it->bidi_p)
30993 {
30994 glyph->resolved_level = it->bidi_it.resolved_level;
30995 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30996 glyph->bidi_type = it->bidi_it.type;
30997 }
30998 else
30999 {
31000 glyph->resolved_level = 0;
31001 glyph->bidi_type = UNKNOWN_BT;
31002 }
31003 ++it->glyph_row->used[area];
31004 }
31005 else
31006 IT_EXPAND_MATRIX_WIDTH (it, area);
31007 }
31008
31009
31010
31011
31012 static void
31013 append_composite_glyph (struct it *it)
31014 {
31015 struct glyph *glyph;
31016 enum glyph_row_area area = it->area;
31017
31018 eassert (it->glyph_row);
31019
31020 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31021 if (glyph < it->glyph_row->glyphs[area + 1])
31022 {
31023
31024
31025 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
31026 {
31027 struct glyph *g;
31028
31029
31030 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31031 g[1] = *g;
31032 glyph = it->glyph_row->glyphs[it->area];
31033 }
31034 glyph->charpos = it->cmp_it.charpos;
31035 glyph->object = it->object;
31036 eassert (it->pixel_width <= SHRT_MAX);
31037 glyph->pixel_width = it->pixel_width;
31038 glyph->ascent = it->ascent;
31039 glyph->descent = it->descent;
31040 glyph->voffset = it->voffset;
31041 glyph->type = COMPOSITE_GLYPH;
31042 if (it->cmp_it.ch < 0)
31043 {
31044 glyph->u.cmp.automatic = false;
31045 glyph->u.cmp.id = it->cmp_it.id;
31046 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
31047 }
31048 else
31049 {
31050 glyph->u.cmp.automatic = true;
31051 glyph->u.cmp.id = it->cmp_it.id;
31052 glyph->slice.cmp.from = it->cmp_it.from;
31053 glyph->slice.cmp.to = it->cmp_it.to - 1;
31054 }
31055 glyph->avoid_cursor_p = it->avoid_cursor_p;
31056 glyph->multibyte_p = it->multibyte_p;
31057 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31058 {
31059
31060
31061 glyph->right_box_line_p = it->start_of_box_run_p;
31062 glyph->left_box_line_p = it->end_of_box_run_p;
31063 }
31064 else
31065 {
31066 glyph->left_box_line_p = it->start_of_box_run_p;
31067 glyph->right_box_line_p = it->end_of_box_run_p;
31068 }
31069 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31070 || it->phys_descent > it->descent);
31071 glyph->padding_p = false;
31072 glyph->glyph_not_available_p = it->glyph_not_available_p;
31073 glyph->face_id = it->face_id;
31074 glyph->font_type = FONT_TYPE_UNKNOWN;
31075 if (it->bidi_p)
31076 {
31077 glyph->resolved_level = it->bidi_it.resolved_level;
31078 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31079 glyph->bidi_type = it->bidi_it.type;
31080 }
31081 ++it->glyph_row->used[area];
31082 }
31083 else
31084 IT_EXPAND_MATRIX_WIDTH (it, area);
31085 }
31086
31087
31088
31089
31090
31091 static void
31092 take_vertical_position_into_account (struct it *it)
31093 {
31094 if (it->voffset)
31095 {
31096 if (it->voffset < 0)
31097
31098
31099 it->ascent -= it->voffset;
31100 else
31101
31102
31103 it->descent += it->voffset;
31104 }
31105 }
31106
31107
31108
31109
31110
31111
31112 static void
31113 produce_image_glyph (struct it *it)
31114 {
31115 struct image *img;
31116 struct face *face;
31117 int glyph_ascent, crop;
31118 struct glyph_slice slice;
31119
31120 eassert (it->what == IT_IMAGE);
31121
31122 face = FACE_FROM_ID (it->f, it->face_id);
31123
31124 prepare_face_for_display (it->f, face);
31125
31126 if (it->image_id < 0)
31127 {
31128
31129 it->ascent = it->phys_ascent = 0;
31130 it->descent = it->phys_descent = 0;
31131 it->pixel_width = 0;
31132 it->nglyphs = 0;
31133 return;
31134 }
31135
31136 img = IMAGE_FROM_ID (it->f, it->image_id);
31137
31138 prepare_image_for_display (it->f, img);
31139
31140 slice.x = slice.y = 0;
31141 slice.width = img->width;
31142 slice.height = img->height;
31143
31144 if (FIXNUMP (it->slice.x))
31145 slice.x = XFIXNUM (it->slice.x);
31146 else if (FLOATP (it->slice.x))
31147 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
31148
31149 if (FIXNUMP (it->slice.y))
31150 slice.y = XFIXNUM (it->slice.y);
31151 else if (FLOATP (it->slice.y))
31152 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
31153
31154 if (FIXNUMP (it->slice.width))
31155 slice.width = XFIXNUM (it->slice.width);
31156 else if (FLOATP (it->slice.width))
31157 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
31158
31159 if (FIXNUMP (it->slice.height))
31160 slice.height = XFIXNUM (it->slice.height);
31161 else if (FLOATP (it->slice.height))
31162 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
31163
31164 if (slice.x >= img->width)
31165 slice.x = img->width;
31166 if (slice.y >= img->height)
31167 slice.y = img->height;
31168 if (slice.x + slice.width >= img->width)
31169 slice.width = img->width - slice.x;
31170 if (slice.y + slice.height > img->height)
31171 slice.height = img->height - slice.y;
31172
31173 if (slice.width == 0 || slice.height == 0)
31174 return;
31175
31176 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
31177
31178 it->descent = slice.height - glyph_ascent;
31179 if (slice.y == 0)
31180 it->descent += img->vmargin;
31181 if (slice.y + slice.height == img->height)
31182 it->descent += img->vmargin;
31183 it->phys_descent = it->descent;
31184
31185 it->pixel_width = slice.width;
31186 if (slice.x == 0)
31187 it->pixel_width += img->hmargin;
31188 if (slice.x + slice.width == img->width)
31189 it->pixel_width += img->hmargin;
31190
31191
31192
31193 if (it->descent < 0)
31194 it->descent = 0;
31195
31196 it->nglyphs = 1;
31197
31198 if (face->box != FACE_NO_BOX)
31199 {
31200
31201
31202 if (face->box_horizontal_line_width > 0)
31203 {
31204 if (slice.y == 0)
31205 it->ascent += face->box_horizontal_line_width;
31206 if (slice.y + slice.height == img->height)
31207 it->descent += face->box_horizontal_line_width;
31208 }
31209
31210 if (face->box_vertical_line_width > 0)
31211 {
31212 if (it->start_of_box_run_p && slice.x == 0)
31213 it->pixel_width += face->box_vertical_line_width;
31214 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
31215 it->pixel_width += face->box_vertical_line_width;
31216 }
31217 }
31218
31219 take_vertical_position_into_account (it);
31220
31221
31222
31223 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
31224 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31225 {
31226 it->pixel_width -= crop;
31227 slice.width -= crop;
31228 }
31229
31230 if (it->glyph_row)
31231 {
31232 struct glyph *glyph;
31233 enum glyph_row_area area = it->area;
31234
31235 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31236 if (it->glyph_row->reversed_p)
31237 {
31238 struct glyph *g;
31239
31240
31241 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31242 g[1] = *g;
31243 glyph = it->glyph_row->glyphs[it->area];
31244 }
31245 if (glyph < it->glyph_row->glyphs[area + 1])
31246 {
31247 glyph->charpos = CHARPOS (it->position);
31248 glyph->object = it->object;
31249 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31250 glyph->ascent = glyph_ascent;
31251 glyph->descent = it->descent;
31252 glyph->voffset = it->voffset;
31253 glyph->type = IMAGE_GLYPH;
31254 glyph->avoid_cursor_p = it->avoid_cursor_p;
31255 glyph->multibyte_p = it->multibyte_p;
31256 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31257 {
31258
31259
31260 glyph->right_box_line_p = it->start_of_box_run_p;
31261 glyph->left_box_line_p = it->end_of_box_run_p;
31262 }
31263 else
31264 {
31265 glyph->left_box_line_p = it->start_of_box_run_p;
31266 glyph->right_box_line_p = it->end_of_box_run_p;
31267 }
31268 glyph->overlaps_vertically_p = false;
31269 glyph->padding_p = false;
31270 glyph->glyph_not_available_p = false;
31271 glyph->face_id = it->face_id;
31272 glyph->u.img_id = img->id;
31273 glyph->slice.img = slice;
31274 glyph->font_type = FONT_TYPE_UNKNOWN;
31275 if (it->bidi_p)
31276 {
31277 glyph->resolved_level = it->bidi_it.resolved_level;
31278 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31279 glyph->bidi_type = it->bidi_it.type;
31280 }
31281 ++it->glyph_row->used[area];
31282 }
31283 else
31284 IT_EXPAND_MATRIX_WIDTH (it, area);
31285 }
31286 }
31287
31288 static void
31289 produce_xwidget_glyph (struct it *it)
31290 {
31291 #ifdef HAVE_XWIDGETS
31292 struct xwidget *xw;
31293 int glyph_ascent, crop;
31294 eassert (it->what == IT_XWIDGET);
31295
31296 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31297
31298 prepare_face_for_display (it->f, face);
31299
31300 xw = it->xwidget;
31301 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31302 it->descent = xw->height/2;
31303 it->phys_descent = it->descent;
31304 it->pixel_width = xw->width;
31305
31306
31307 if (it->descent < 0)
31308 it->descent = 0;
31309
31310 it->nglyphs = 1;
31311
31312 if (face->box != FACE_NO_BOX)
31313 {
31314 if (face->box_horizontal_line_width > 0)
31315 {
31316 it->ascent += face->box_horizontal_line_width;
31317 it->descent += face->box_horizontal_line_width;
31318 }
31319
31320 if (face->box_vertical_line_width > 0)
31321 {
31322 if (it->start_of_box_run_p)
31323 it->pixel_width += face->box_vertical_line_width;
31324 it->pixel_width += face->box_vertical_line_width;
31325 }
31326 }
31327
31328 take_vertical_position_into_account (it);
31329
31330
31331
31332 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31333 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31334 it->pixel_width -= crop;
31335
31336 if (it->glyph_row)
31337 {
31338 enum glyph_row_area area = it->area;
31339 struct glyph *glyph
31340 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31341
31342 if (it->glyph_row->reversed_p)
31343 {
31344 struct glyph *g;
31345
31346
31347 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31348 g[1] = *g;
31349 glyph = it->glyph_row->glyphs[it->area];
31350 }
31351 if (glyph < it->glyph_row->glyphs[area + 1])
31352 {
31353 glyph->charpos = CHARPOS (it->position);
31354 glyph->object = it->object;
31355 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31356 glyph->ascent = glyph_ascent;
31357 glyph->descent = it->descent;
31358 glyph->voffset = it->voffset;
31359 glyph->type = XWIDGET_GLYPH;
31360 glyph->avoid_cursor_p = it->avoid_cursor_p;
31361 glyph->multibyte_p = it->multibyte_p;
31362 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31363 {
31364
31365
31366 glyph->right_box_line_p = it->start_of_box_run_p;
31367 glyph->left_box_line_p = it->end_of_box_run_p;
31368 }
31369 else
31370 {
31371 glyph->left_box_line_p = it->start_of_box_run_p;
31372 glyph->right_box_line_p = it->end_of_box_run_p;
31373 }
31374 glyph->overlaps_vertically_p = 0;
31375 glyph->padding_p = 0;
31376 glyph->glyph_not_available_p = 0;
31377 glyph->face_id = it->face_id;
31378 glyph->u.xwidget = it->xwidget->xwidget_id;
31379 glyph->font_type = FONT_TYPE_UNKNOWN;
31380 if (it->bidi_p)
31381 {
31382 glyph->resolved_level = it->bidi_it.resolved_level;
31383 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31384 glyph->bidi_type = it->bidi_it.type;
31385 }
31386 ++it->glyph_row->used[area];
31387 }
31388 else
31389 IT_EXPAND_MATRIX_WIDTH (it, area);
31390 }
31391 #endif
31392 }
31393
31394
31395
31396
31397
31398 static void
31399 append_stretch_glyph (struct it *it, Lisp_Object object,
31400 int width, int height, int ascent)
31401 {
31402 struct glyph *glyph;
31403 enum glyph_row_area area = it->area;
31404
31405 eassert (ascent >= 0 && ascent <= height);
31406
31407 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31408 if (glyph < it->glyph_row->glyphs[area + 1])
31409 {
31410
31411
31412 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31413 {
31414 struct glyph *g;
31415
31416
31417 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31418 g[1] = *g;
31419 glyph = it->glyph_row->glyphs[area];
31420
31421
31422
31423
31424
31425
31426
31427
31428
31429
31430
31431
31432
31433
31434
31435 if (it->current_x < it->first_visible_x)
31436 width -= it->first_visible_x - it->current_x;
31437 eassert (width > 0);
31438 }
31439 glyph->charpos = CHARPOS (it->position);
31440 glyph->object = object;
31441
31442
31443 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31444 glyph->ascent = ascent;
31445 glyph->descent = height - ascent;
31446 glyph->voffset = it->voffset;
31447 glyph->type = STRETCH_GLYPH;
31448 glyph->avoid_cursor_p = it->avoid_cursor_p;
31449 glyph->multibyte_p = it->multibyte_p;
31450 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31451 {
31452
31453
31454 glyph->right_box_line_p = it->start_of_box_run_p;
31455 glyph->left_box_line_p = it->end_of_box_run_p;
31456 }
31457 else
31458 {
31459 glyph->left_box_line_p = it->start_of_box_run_p;
31460 glyph->right_box_line_p = it->end_of_box_run_p;
31461 }
31462 glyph->overlaps_vertically_p = false;
31463 glyph->padding_p = false;
31464 glyph->glyph_not_available_p = false;
31465 glyph->face_id = it->face_id;
31466 glyph->u.stretch.ascent = ascent;
31467 glyph->u.stretch.height = height;
31468 glyph->slice.img = null_glyph_slice;
31469 glyph->font_type = FONT_TYPE_UNKNOWN;
31470 if (it->bidi_p)
31471 {
31472 glyph->resolved_level = it->bidi_it.resolved_level;
31473 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31474 glyph->bidi_type = it->bidi_it.type;
31475 }
31476 else
31477 {
31478 glyph->resolved_level = 0;
31479 glyph->bidi_type = UNKNOWN_BT;
31480 }
31481 ++it->glyph_row->used[area];
31482 }
31483 else
31484 IT_EXPAND_MATRIX_WIDTH (it, area);
31485 }
31486
31487 #endif
31488
31489
31490
31491
31492
31493
31494
31495
31496
31497
31498
31499
31500
31501
31502
31503
31504
31505
31506
31507
31508
31509
31510
31511
31512
31513
31514
31515
31516
31517
31518
31519
31520 void
31521 produce_stretch_glyph (struct it *it)
31522 {
31523
31524 Lisp_Object prop, plist;
31525 int width = 0, height = 0, align_to = -1;
31526 bool zero_width_ok_p = false;
31527 double tem;
31528 struct font *font = NULL;
31529
31530 #ifdef HAVE_WINDOW_SYSTEM
31531 int ascent = 0;
31532 bool zero_height_ok_p = false;
31533 struct face *face = NULL;
31534
31535 if (FRAME_WINDOW_P (it->f))
31536 {
31537 face = FACE_FROM_ID (it->f, it->face_id);
31538 font = face->font ? face->font : FRAME_FONT (it->f);
31539 prepare_face_for_display (it->f, face);
31540 }
31541 #endif
31542
31543
31544 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31545 plist = XCDR (it->object);
31546
31547
31548 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31549 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31550 {
31551
31552 zero_width_ok_p = true;
31553 width = (int)tem;
31554 }
31555 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31556 {
31557
31558
31559
31560 struct it it2;
31561 Lisp_Object object =
31562 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31563 unsigned char *p = (STRINGP (object)
31564 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31565 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31566 bool multibyte_p =
31567 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31568
31569 it2 = *it;
31570 if (multibyte_p)
31571 {
31572 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31573 #ifdef HAVE_WINDOW_SYSTEM
31574 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31575 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31576 IT_CHARPOS (*it),
31577 STRINGP (object)? object : Qnil);
31578 #endif
31579 }
31580 else
31581 {
31582 it2.c = it2.char_to_display = *p, it2.len = 1;
31583 if (! ASCII_CHAR_P (it2.c))
31584 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31585 }
31586
31587 it2.glyph_row = NULL;
31588 it2.what = IT_CHARACTER;
31589 PRODUCE_GLYPHS (&it2);
31590 width = NUMVAL (prop) * it2.pixel_width;
31591 }
31592 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31593 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31594 &align_to))
31595 {
31596 int x = it->current_x + it->continuation_lines_width;
31597 int x0 = x;
31598
31599 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31600 {
31601 x -= it->lnum_pixel_width;
31602
31603 if (x + it->stretch_adjust >= it->first_visible_x)
31604 x += it->stretch_adjust;
31605 }
31606
31607 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31608 align_to = (align_to < 0
31609 ? 0
31610 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31611 else if (align_to < 0)
31612 align_to = window_box_left_offset (it->w, TEXT_AREA);
31613 width = max (0, (int)tem + align_to - x);
31614
31615 int next_x = x + width;
31616 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31617 {
31618
31619
31620 if (x < it->first_visible_x)
31621 {
31622 next_x -= it->first_visible_x - x;
31623 it->stretch_adjust = it->first_visible_x - x;
31624 }
31625 else
31626 next_x -= it->stretch_adjust;
31627 }
31628 width = next_x - x0;
31629 zero_width_ok_p = true;
31630 }
31631 else
31632
31633 width = FRAME_COLUMN_WIDTH (it->f);
31634
31635 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31636 width = 1;
31637
31638 #ifdef HAVE_WINDOW_SYSTEM
31639
31640 if (FRAME_WINDOW_P (it->f))
31641 {
31642 int default_height = normal_char_height (font, ' ');
31643
31644 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31645 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31646 {
31647 height = (int)tem;
31648 zero_height_ok_p = true;
31649 }
31650 else if (prop = plist_get (plist, QCrelative_height),
31651 NUMVAL (prop) > 0)
31652 height = default_height * NUMVAL (prop);
31653 else
31654 height = default_height;
31655
31656 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31657 height = 1;
31658
31659
31660
31661
31662 if (prop = plist_get (plist, QCascent),
31663 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31664 ascent = height * NUMVAL (prop) / 100.0;
31665 else if (!NILP (prop)
31666 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31667 ascent = min (max (0, (int)tem), height);
31668 else
31669 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31670 }
31671 else
31672 #endif
31673 height = 1;
31674
31675 if (width > 0
31676 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31677 && it->current_x + width > it->last_visible_x)
31678 {
31679 width = it->last_visible_x - it->current_x;
31680 #ifdef HAVE_WINDOW_SYSTEM
31681
31682
31683 width -= FRAME_WINDOW_P (it->f);
31684 #endif
31685 }
31686
31687 if (width > 0 && height > 0 && it->glyph_row)
31688 {
31689 Lisp_Object o_object = it->object;
31690 Lisp_Object object =
31691 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31692 int n = width;
31693
31694 if (!STRINGP (object))
31695 object = it->w->contents;
31696 #ifdef HAVE_WINDOW_SYSTEM
31697 if (FRAME_WINDOW_P (it->f))
31698 append_stretch_glyph (it, object, width, height, ascent);
31699 else
31700 #endif
31701 {
31702 it->object = object;
31703 it->char_to_display = ' ';
31704 it->pixel_width = it->len = 1;
31705 while (n--)
31706 tty_append_glyph (it);
31707 it->object = o_object;
31708 }
31709 }
31710
31711 it->pixel_width = width;
31712 #ifdef HAVE_WINDOW_SYSTEM
31713 if (FRAME_WINDOW_P (it->f))
31714 {
31715 it->ascent = it->phys_ascent = ascent;
31716 it->descent = it->phys_descent = height - it->ascent;
31717 it->nglyphs = width > 0 && height > 0;
31718 take_vertical_position_into_account (it);
31719 }
31720 else
31721 #endif
31722 it->nglyphs = width;
31723 }
31724
31725
31726
31727
31728
31729
31730
31731 static void
31732 produce_special_glyphs (struct it *it, enum display_element_type what)
31733 {
31734 struct it temp_it;
31735 Lisp_Object gc;
31736 GLYPH glyph;
31737
31738 temp_it = *it;
31739 temp_it.object = Qnil;
31740 memset (&temp_it.current, 0, sizeof temp_it.current);
31741
31742 if (what == IT_CONTINUATION)
31743 {
31744
31745 if (it->bidi_it.paragraph_dir == R2L)
31746 SET_GLYPH_FROM_CHAR (glyph, '/');
31747 else
31748 SET_GLYPH_FROM_CHAR (glyph, '\\');
31749 if (it->dp
31750 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31751 {
31752
31753 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31754 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31755 }
31756 }
31757 else if (what == IT_TRUNCATION)
31758 {
31759
31760 SET_GLYPH_FROM_CHAR (glyph, '$');
31761 if (it->dp
31762 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31763 {
31764
31765 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31766 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31767 }
31768 }
31769 else
31770 emacs_abort ();
31771
31772 #ifdef HAVE_WINDOW_SYSTEM
31773
31774
31775
31776
31777
31778 if (FRAME_WINDOW_P (temp_it.f)
31779
31780
31781
31782 && temp_it.glyph_row
31783
31784
31785
31786 && temp_it.glyph_row->used[TEXT_AREA] > 0
31787 && (temp_it.glyph_row->reversed_p
31788 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31789 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31790 {
31791 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31792
31793 if (stretch_width > 0)
31794 {
31795 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31796 struct font *font =
31797 face->font ? face->font : FRAME_FONT (temp_it.f);
31798 int stretch_ascent =
31799 (((temp_it.ascent + temp_it.descent)
31800 * FONT_BASE (font)) / FONT_HEIGHT (font));
31801
31802 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31803 temp_it.ascent + temp_it.descent,
31804 stretch_ascent);
31805 }
31806 }
31807 #endif
31808
31809 temp_it.dp = NULL;
31810 temp_it.what = IT_CHARACTER;
31811 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31812 temp_it.face_id = GLYPH_FACE (glyph);
31813 temp_it.len = CHAR_BYTES (temp_it.c);
31814
31815 PRODUCE_GLYPHS (&temp_it);
31816 it->pixel_width = temp_it.pixel_width;
31817 it->nglyphs = temp_it.nglyphs;
31818 }
31819
31820
31821
31822
31823
31824
31825
31826
31827
31828 static void
31829 pad_mode_line (struct it *it, bool mode_line_p)
31830 {
31831 struct it temp_it;
31832 GLYPH glyph;
31833
31834 eassert (!FRAME_WINDOW_P (it->f));
31835 temp_it = *it;
31836 temp_it.object = Qnil;
31837 memset (&temp_it.current, 0, sizeof temp_it.current);
31838
31839 SET_GLYPH (glyph, mode_line_p ? '-' : ' ', it->base_face_id);
31840
31841 temp_it.dp = NULL;
31842 temp_it.what = IT_CHARACTER;
31843 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31844 temp_it.face_id = GLYPH_FACE (glyph);
31845 temp_it.len = CHAR_BYTES (temp_it.c);
31846
31847 PRODUCE_GLYPHS (&temp_it);
31848 it->pixel_width = temp_it.pixel_width;
31849 it->nglyphs = temp_it.nglyphs;
31850 }
31851
31852 #ifdef HAVE_WINDOW_SYSTEM
31853
31854
31855
31856
31857
31858
31859
31860
31861
31862 static Lisp_Object
31863 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31864 int boff, bool override)
31865 {
31866 Lisp_Object face_name = Qnil;
31867 int ascent, descent, height;
31868
31869 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31870 return val;
31871
31872 if (CONSP (val))
31873 {
31874 face_name = XCAR (val);
31875 val = XCDR (val);
31876 if (!NUMBERP (val))
31877 val = make_fixnum (1);
31878 if (NILP (face_name))
31879 {
31880 height = it->ascent + it->descent;
31881 goto scale;
31882 }
31883 }
31884
31885 if (NILP (face_name))
31886 {
31887 font = FRAME_FONT (it->f);
31888 boff = FRAME_BASELINE_OFFSET (it->f);
31889 }
31890 else if (EQ (face_name, Qt))
31891 {
31892 override = false;
31893 }
31894 else
31895 {
31896 int face_id;
31897 struct face *face;
31898
31899 face_id = lookup_named_face (it->w, it->f, face_name, false);
31900 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31901 if (face == NULL || ((font = face->font) == NULL))
31902 return make_fixnum (-1);
31903 boff = font->baseline_offset;
31904 if (font->vertical_centering)
31905 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31906 }
31907
31908 normal_char_ascent_descent (font, -1, &ascent, &descent);
31909
31910 if (override)
31911 {
31912 it->override_ascent = ascent;
31913 it->override_descent = descent;
31914 it->override_boff = boff;
31915 }
31916
31917 height = ascent + descent;
31918
31919 scale:
31920
31921 if (FLOATP (val))
31922 height = (int)(XFLOAT_DATA (val) * height);
31923 else if (INTEGERP (val))
31924 {
31925 intmax_t v;
31926 if (integer_to_intmax (val, &v))
31927 height *= v;
31928 }
31929
31930 return make_fixnum (height);
31931 }
31932
31933
31934
31935
31936
31937
31938
31939
31940
31941
31942
31943
31944
31945
31946 static void
31947 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
31948 short upper_xoff, short upper_yoff,
31949 short lower_xoff, short lower_yoff)
31950 {
31951 struct glyph *glyph;
31952 enum glyph_row_area area = it->area;
31953
31954 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31955 if (glyph < it->glyph_row->glyphs[area + 1])
31956 {
31957
31958
31959 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31960 {
31961 struct glyph *g;
31962
31963
31964 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31965 g[1] = *g;
31966 glyph = it->glyph_row->glyphs[area];
31967 }
31968 glyph->charpos = CHARPOS (it->position);
31969 glyph->object = it->object;
31970 eassert (it->pixel_width <= SHRT_MAX);
31971 glyph->pixel_width = it->pixel_width;
31972 glyph->ascent = it->ascent;
31973 glyph->descent = it->descent;
31974 glyph->voffset = it->voffset;
31975 glyph->type = GLYPHLESS_GLYPH;
31976 glyph->u.glyphless.method = it->glyphless_method;
31977 glyph->u.glyphless.for_no_font = for_no_font;
31978 glyph->u.glyphless.len = len;
31979 glyph->u.glyphless.ch = it->c;
31980 glyph->slice.glyphless.upper_xoff = upper_xoff;
31981 glyph->slice.glyphless.upper_yoff = upper_yoff;
31982 glyph->slice.glyphless.lower_xoff = lower_xoff;
31983 glyph->slice.glyphless.lower_yoff = lower_yoff;
31984 glyph->avoid_cursor_p = it->avoid_cursor_p;
31985 glyph->multibyte_p = it->multibyte_p;
31986 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31987 {
31988
31989
31990 glyph->right_box_line_p = it->start_of_box_run_p;
31991 glyph->left_box_line_p = it->end_of_box_run_p;
31992 }
31993 else
31994 {
31995 glyph->left_box_line_p = it->start_of_box_run_p;
31996 glyph->right_box_line_p = it->end_of_box_run_p;
31997 }
31998 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31999 || it->phys_descent > it->descent);
32000 glyph->padding_p = false;
32001 glyph->glyph_not_available_p = false;
32002 glyph->face_id = face_id;
32003 glyph->font_type = FONT_TYPE_UNKNOWN;
32004 if (it->bidi_p)
32005 {
32006 glyph->resolved_level = it->bidi_it.resolved_level;
32007 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
32008 glyph->bidi_type = it->bidi_it.type;
32009 }
32010 ++it->glyph_row->used[area];
32011 }
32012 else
32013 IT_EXPAND_MATRIX_WIDTH (it, area);
32014 }
32015
32016
32017
32018
32019
32020
32021
32022
32023
32024
32025
32026 static void
32027 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
32028 {
32029 int face_id;
32030 struct face *face;
32031 struct font *font;
32032 int base_width, base_height, width, height;
32033 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
32034 int len;
32035
32036
32037
32038 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
32039 font = face->font ? face->font : FRAME_FONT (it->f);
32040 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
32041 it->ascent += font->baseline_offset;
32042 it->descent -= font->baseline_offset;
32043 base_height = it->ascent + it->descent;
32044 base_width = font->average_width;
32045
32046 face_id = merge_glyphless_glyph_face (it);
32047
32048 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
32049 {
32050 it->pixel_width = THIN_SPACE_WIDTH;
32051 len = 0;
32052 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32053 }
32054 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
32055 {
32056 width = CHARACTER_WIDTH (it->c);
32057 if (width == 0)
32058 width = 1;
32059 else if (width > 4)
32060 width = 4;
32061 it->pixel_width = base_width * width;
32062 len = 0;
32063 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32064 }
32065 else
32066 {
32067 char buf[7];
32068 const char *str;
32069 unsigned int code[6];
32070 int upper_len;
32071 int ascent, descent;
32072 struct font_metrics metrics_upper, metrics_lower;
32073
32074 face = FACE_FROM_ID (it->f, face_id);
32075 font = face->font ? face->font : FRAME_FONT (it->f);
32076 prepare_face_for_display (it->f, face);
32077
32078 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
32079 {
32080 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
32081 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
32082 if (CONSP (acronym))
32083 acronym = XCAR (acronym);
32084 str = STRINGP (acronym) ? SSDATA (acronym) : "";
32085 }
32086 else
32087 {
32088 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
32089 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
32090 str = buf;
32091 }
32092 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
32093 code[len] = font->driver->encode_char (font, str[len]);
32094 upper_len = (len + 1) / 2;
32095 font->driver->text_extents (font, code, upper_len,
32096 &metrics_upper);
32097 font->driver->text_extents (font, code + upper_len, len - upper_len,
32098 &metrics_lower);
32099
32100
32101
32102
32103 width = max (metrics_upper.width, metrics_lower.width) + 4;
32104 upper_xoff = lower_xoff = 2;
32105 if (base_width >= width)
32106 {
32107
32108 it->pixel_width = base_width;
32109 lower_xoff = base_width - 2 - metrics_lower.width;
32110 }
32111 else
32112 {
32113
32114 it->pixel_width = width;
32115 if (metrics_upper.width >= metrics_lower.width)
32116 lower_xoff = (width - metrics_lower.width) / 2;
32117 else
32118 upper_xoff = (width - metrics_upper.width) / 2;
32119 }
32120
32121
32122
32123 height = (metrics_upper.ascent + metrics_upper.descent
32124 + metrics_lower.ascent + metrics_lower.descent) + 5;
32125
32126
32127
32128
32129
32130
32131
32132
32133 ascent = - (it->descent - (base_height + height + 1) / 2);
32134 descent = it->descent - (base_height - height) / 2;
32135 lower_yoff = descent - 2 - metrics_lower.descent;
32136 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
32137 - metrics_upper.descent);
32138
32139 if (height > base_height)
32140 {
32141 it->ascent = ascent;
32142 it->descent = descent;
32143 }
32144 }
32145
32146 it->phys_ascent = it->ascent;
32147 it->phys_descent = it->descent;
32148 if (it->glyph_row)
32149 append_glyphless_glyph (it, face_id, for_no_font, len,
32150 upper_xoff, upper_yoff,
32151 lower_xoff, lower_yoff);
32152 it->nglyphs = 1;
32153 take_vertical_position_into_account (it);
32154 }
32155
32156
32157
32158
32159
32160 #define IT_APPLY_FACE_BOX(it, face) \
32161 do { \
32162 if (face->box != FACE_NO_BOX) \
32163 { \
32164 int thick = face->box_horizontal_line_width; \
32165 if (thick > 0) \
32166 { \
32167 it->ascent += thick; \
32168 it->descent += thick; \
32169 } \
32170 \
32171 thick = face->box_vertical_line_width; \
32172 if (thick > 0) \
32173 { \
32174 if (it->start_of_box_run_p) \
32175 it->pixel_width += thick; \
32176 if (it->end_of_box_run_p) \
32177 it->pixel_width += thick; \
32178 } \
32179 } \
32180 } while (false)
32181
32182
32183
32184
32185
32186
32187 void
32188 gui_produce_glyphs (struct it *it)
32189 {
32190 int extra_line_spacing = it->extra_line_spacing;
32191
32192 it->glyph_not_available_p = false;
32193
32194 if (it->what == IT_CHARACTER)
32195 {
32196 unsigned char2b;
32197 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32198 struct font *font = face->font;
32199 struct font_metrics *pcm = NULL;
32200 int boff;
32201
32202 if (font == NULL)
32203 {
32204
32205
32206
32207 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
32208
32209 eassert (it->what == IT_GLYPHLESS);
32210 produce_glyphless_glyph (it, true,
32211 STRINGP (acronym) ? acronym : Qnil);
32212 goto done;
32213 }
32214
32215 boff = font->baseline_offset;
32216 if (font->vertical_centering)
32217 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32218
32219 if (it->char_to_display != '\n' && it->char_to_display != '\t')
32220 {
32221 it->nglyphs = 1;
32222
32223 if (it->override_ascent >= 0)
32224 {
32225 it->ascent = it->override_ascent;
32226 it->descent = it->override_descent;
32227 boff = it->override_boff;
32228 }
32229 else
32230 {
32231 it->ascent = FONT_BASE (font) + boff;
32232 it->descent = FONT_DESCENT (font) - boff;
32233 }
32234
32235 if (get_char_glyph_code (it->char_to_display, font, &char2b))
32236 {
32237 pcm = get_per_char_metric (font, &char2b);
32238 if (pcm->width == 0
32239 && pcm->rbearing == 0 && pcm->lbearing == 0)
32240 pcm = NULL;
32241 }
32242
32243 if (pcm)
32244 {
32245 it->phys_ascent = pcm->ascent + boff;
32246 it->phys_descent = pcm->descent - boff;
32247 it->pixel_width = pcm->width;
32248
32249
32250 if (it->override_ascent < 0)
32251 {
32252 if (FONT_TOO_HIGH (font))
32253 {
32254 it->ascent = it->phys_ascent;
32255 it->descent = it->phys_descent;
32256
32257
32258 if (it->ascent < 0)
32259 it->ascent = 0;
32260 if (it->descent < 0)
32261 it->descent = 0;
32262 }
32263 }
32264 }
32265 else
32266 {
32267 it->glyph_not_available_p = true;
32268 it->phys_ascent = it->ascent;
32269 it->phys_descent = it->descent;
32270 it->pixel_width = font->space_width;
32271 }
32272
32273 if (it->constrain_row_ascent_descent_p)
32274 {
32275 if (it->descent > it->max_descent)
32276 {
32277 it->ascent += it->descent - it->max_descent;
32278 it->descent = it->max_descent;
32279 }
32280 if (it->ascent > it->max_ascent)
32281 {
32282 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32283 it->ascent = it->max_ascent;
32284 }
32285 it->phys_ascent = min (it->phys_ascent, it->ascent);
32286 it->phys_descent = min (it->phys_descent, it->descent);
32287 extra_line_spacing = 0;
32288 }
32289
32290
32291
32292 bool stretched_p
32293 = it->char_to_display == ' ' && !NILP (it->space_width);
32294 if (stretched_p)
32295 it->pixel_width *= XFLOATINT (it->space_width);
32296
32297 IT_APPLY_FACE_BOX(it, face);
32298
32299
32300
32301 if (face->overline_p)
32302 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32303
32304 if (it->constrain_row_ascent_descent_p)
32305 {
32306 if (it->ascent > it->max_ascent)
32307 it->ascent = it->max_ascent;
32308 if (it->descent > it->max_descent)
32309 it->descent = it->max_descent;
32310 }
32311
32312 take_vertical_position_into_account (it);
32313
32314
32315 if (it->glyph_row)
32316 {
32317 if (stretched_p)
32318 {
32319
32320
32321 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32322 / FONT_HEIGHT (font));
32323 append_stretch_glyph (it, it->object, it->pixel_width,
32324 it->ascent + it->descent, ascent);
32325 }
32326 else
32327 append_glyph (it);
32328
32329
32330
32331
32332 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32333 it->glyph_row->contains_overlapping_glyphs_p = true;
32334 }
32335 if (! stretched_p && it->pixel_width == 0)
32336
32337
32338 it->pixel_width = 1;
32339 }
32340 else if (it->char_to_display == '\n')
32341 {
32342
32343
32344
32345
32346 Lisp_Object height;
32347 Lisp_Object total_height = Qnil;
32348
32349 it->override_ascent = -1;
32350 it->pixel_width = 0;
32351 it->nglyphs = 0;
32352
32353 height = get_it_property (it, Qline_height);
32354
32355 if (CONSP (height)
32356 && CONSP (XCDR (height))
32357 && NILP (XCDR (XCDR (height))))
32358 {
32359 total_height = XCAR (XCDR (height));
32360 height = XCAR (height);
32361 }
32362 height = calc_line_height_property (it, height, font, boff, true);
32363
32364 if (it->override_ascent >= 0)
32365 {
32366 it->ascent = it->override_ascent;
32367 it->descent = it->override_descent;
32368 boff = it->override_boff;
32369 }
32370 else
32371 {
32372 if (FONT_TOO_HIGH (font))
32373 {
32374 it->ascent = font->pixel_size + boff - 1;
32375 it->descent = -boff + 1;
32376 if (it->descent < 0)
32377 it->descent = 0;
32378 }
32379 else
32380 {
32381 it->ascent = FONT_BASE (font) + boff;
32382 it->descent = FONT_DESCENT (font) - boff;
32383 }
32384 }
32385
32386 if (EQ (height, Qt))
32387 {
32388 if (it->descent > it->max_descent)
32389 {
32390 it->ascent += it->descent - it->max_descent;
32391 it->descent = it->max_descent;
32392 }
32393 if (it->ascent > it->max_ascent)
32394 {
32395 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32396 it->ascent = it->max_ascent;
32397 }
32398 it->phys_ascent = min (it->phys_ascent, it->ascent);
32399 it->phys_descent = min (it->phys_descent, it->descent);
32400 it->constrain_row_ascent_descent_p = true;
32401 extra_line_spacing = 0;
32402 }
32403 else
32404 {
32405 Lisp_Object spacing;
32406
32407 it->phys_ascent = it->ascent;
32408 it->phys_descent = it->descent;
32409
32410 if ((it->max_ascent > 0 || it->max_descent > 0)
32411 && face->box != FACE_NO_BOX
32412 && face->box_horizontal_line_width > 0)
32413 {
32414 it->ascent += face->box_horizontal_line_width;
32415 it->descent += face->box_horizontal_line_width;
32416 }
32417 if (!NILP (height)
32418 && XFIXNUM (height) > it->ascent + it->descent)
32419 it->ascent = XFIXNUM (height) - it->descent;
32420
32421 if (!NILP (total_height))
32422 spacing = calc_line_height_property (it, total_height, font,
32423 boff, false);
32424 else
32425 {
32426 spacing = get_it_property (it, Qline_spacing);
32427 spacing = calc_line_height_property (it, spacing, font,
32428 boff, false);
32429 }
32430 if (FIXNUMP (spacing))
32431 {
32432 extra_line_spacing = XFIXNUM (spacing);
32433 if (!NILP (total_height))
32434 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32435 }
32436 }
32437 }
32438 else
32439 {
32440 if (font->space_width > 0)
32441 {
32442 int tab_width = it->tab_width * font->space_width;
32443 int x = it->current_x + it->continuation_lines_width;
32444 int x0 = x;
32445
32446 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32447 {
32448 x -= it->lnum_pixel_width;
32449
32450 if (x + it->stretch_adjust >= it->first_visible_x)
32451 x += it->stretch_adjust;
32452 }
32453
32454 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32455
32456
32457
32458
32459 if (next_tab_x - x < font->space_width)
32460 next_tab_x += tab_width;
32461 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32462 {
32463 next_tab_x += it->lnum_pixel_width;
32464
32465
32466 if (x < it->first_visible_x)
32467 {
32468 next_tab_x -= it->first_visible_x - x;
32469 it->stretch_adjust = it->first_visible_x - x;
32470 }
32471 else
32472 next_tab_x -= it->stretch_adjust;
32473 }
32474
32475 it->pixel_width = next_tab_x - x0;
32476 it->nglyphs = 1;
32477 if (FONT_TOO_HIGH (font))
32478 {
32479 if (get_char_glyph_code (' ', font, &char2b))
32480 {
32481 pcm = get_per_char_metric (font, &char2b);
32482 if (pcm->width == 0
32483 && pcm->rbearing == 0 && pcm->lbearing == 0)
32484 pcm = NULL;
32485 }
32486
32487 if (pcm)
32488 {
32489 it->ascent = pcm->ascent + boff;
32490 it->descent = pcm->descent - boff;
32491 }
32492 else
32493 {
32494 it->ascent = font->pixel_size + boff - 1;
32495 it->descent = -boff + 1;
32496 }
32497 if (it->ascent < 0)
32498 it->ascent = 0;
32499 if (it->descent < 0)
32500 it->descent = 0;
32501 }
32502 else
32503 {
32504 it->ascent = FONT_BASE (font) + boff;
32505 it->descent = FONT_DESCENT (font) - boff;
32506 }
32507 it->phys_ascent = it->ascent;
32508 it->phys_descent = it->descent;
32509
32510 if (it->glyph_row)
32511 {
32512 append_stretch_glyph (it, it->object, it->pixel_width,
32513 it->ascent + it->descent, it->ascent);
32514 }
32515 }
32516 else
32517 {
32518 it->pixel_width = 0;
32519 it->nglyphs = 1;
32520 }
32521 }
32522
32523 if (FONT_TOO_HIGH (font))
32524 {
32525 int font_ascent, font_descent;
32526
32527
32528
32529
32530
32531
32532
32533
32534 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32535 it->max_ascent = max (it->max_ascent, font_ascent);
32536 it->max_descent = max (it->max_descent, font_descent);
32537 }
32538
32539 if (it->ascent < 0)
32540 it->ascent = 0;
32541 if (it->descent < 0)
32542 it->descent = 0;
32543 }
32544 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32545 {
32546
32547
32548
32549
32550
32551
32552
32553
32554 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32555 int boff;
32556 struct composition *cmp = composition_table[it->cmp_it.id];
32557 int glyph_len = cmp->glyph_len;
32558 struct font *font = face->font;
32559
32560 it->nglyphs = 1;
32561
32562
32563
32564
32565
32566
32567
32568
32569 if (! cmp->font || cmp->font != font)
32570 {
32571
32572
32573
32574
32575 int font_ascent, font_descent, font_height;
32576
32577 int leftmost, rightmost, lowest, highest;
32578 int lbearing, rbearing;
32579 int i, width, ascent, descent;
32580 int c;
32581 unsigned char2b;
32582 struct font_metrics *pcm;
32583 ptrdiff_t pos;
32584
32585 eassume (0 < glyph_len);
32586 do
32587 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32588 while (c == '\t' && 0 < --glyph_len);
32589
32590 bool right_padded = glyph_len < cmp->glyph_len;
32591 for (i = 0; i < glyph_len; i++)
32592 {
32593 c = COMPOSITION_GLYPH (cmp, i);
32594 if (c != '\t')
32595 break;
32596 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32597 }
32598 bool left_padded = i > 0;
32599
32600 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32601 : IT_CHARPOS (*it));
32602
32603 bool font_not_found_p = font == NULL;
32604 if (font_not_found_p)
32605 {
32606 face = face->ascii_face;
32607 font = face->font;
32608 }
32609 boff = font->baseline_offset;
32610 if (font->vertical_centering)
32611 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32612 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32613 font_ascent += boff;
32614 font_descent -= boff;
32615 font_height = font_ascent + font_descent;
32616
32617 cmp->font = font;
32618
32619 pcm = NULL;
32620 if (! font_not_found_p)
32621 {
32622 get_char_face_and_encoding (it->f, c, it->face_id,
32623 &char2b, false);
32624 pcm = get_per_char_metric (font, &char2b);
32625 }
32626
32627
32628 if (pcm)
32629 {
32630 width = cmp->glyph_len > 0 ? pcm->width : 0;
32631 ascent = pcm->ascent;
32632 descent = pcm->descent;
32633 lbearing = pcm->lbearing;
32634 rbearing = pcm->rbearing;
32635 }
32636 else
32637 {
32638 width = cmp->glyph_len > 0 ? font->space_width : 0;
32639 ascent = FONT_BASE (font);
32640 descent = FONT_DESCENT (font);
32641 lbearing = 0;
32642 rbearing = width;
32643 }
32644
32645 rightmost = width;
32646 leftmost = 0;
32647 lowest = - descent + boff;
32648 highest = ascent + boff;
32649
32650 if (! font_not_found_p
32651 && font->default_ascent
32652 && CHAR_TABLE_P (Vuse_default_ascent)
32653 && !NILP (Faref (Vuse_default_ascent,
32654 make_fixnum (it->char_to_display))))
32655 highest = font->default_ascent + boff;
32656
32657
32658
32659
32660 cmp->offsets[i * 2] = 0;
32661 cmp->offsets[i * 2 + 1] = boff;
32662 cmp->lbearing = lbearing;
32663 cmp->rbearing = rbearing;
32664
32665
32666 for (i++; i < glyph_len; i++)
32667 {
32668 int left, right, btm, top;
32669 int ch = COMPOSITION_GLYPH (cmp, i);
32670 int face_id;
32671 struct face *this_face;
32672
32673 if (ch == '\t')
32674 ch = ' ';
32675 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32676 this_face = FACE_FROM_ID (it->f, face_id);
32677 font = this_face->font;
32678
32679 if (font == NULL)
32680 pcm = NULL;
32681 else
32682 {
32683 get_char_face_and_encoding (it->f, ch, face_id,
32684 &char2b, false);
32685 pcm = get_per_char_metric (font, &char2b);
32686 }
32687 if (! pcm)
32688 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32689 else
32690 {
32691 width = pcm->width;
32692 ascent = pcm->ascent;
32693 descent = pcm->descent;
32694 lbearing = pcm->lbearing;
32695 rbearing = pcm->rbearing;
32696 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32697 {
32698
32699
32700 left = (leftmost + rightmost - width) / 2;
32701 btm = - descent + boff;
32702 if (font->relative_compose
32703 && (! CHAR_TABLE_P (Vignore_relative_composition)
32704 || NILP (Faref (Vignore_relative_composition,
32705 make_fixnum (ch)))))
32706 {
32707
32708 if (- descent >= font->relative_compose)
32709
32710 btm = highest + 1;
32711 else if (ascent <= 0)
32712
32713 btm = lowest - 1 - ascent - descent;
32714 }
32715 }
32716 else
32717 {
32718
32719
32720
32721
32722
32723
32724
32725
32726
32727
32728
32729
32730
32731
32732
32733 int rule = COMPOSITION_RULE (cmp, i);
32734 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32735
32736 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32737 grefx = gref % 3, nrefx = nref % 3;
32738 grefy = gref / 3, nrefy = nref / 3;
32739 if (xoff)
32740 xoff = font_height * (xoff - 128) / 256;
32741 if (yoff)
32742 yoff = font_height * (yoff - 128) / 256;
32743
32744 left = (leftmost
32745 + grefx * (rightmost - leftmost) / 2
32746 - nrefx * width / 2
32747 + xoff);
32748
32749 btm = ((grefy == 0 ? highest
32750 : grefy == 1 ? 0
32751 : grefy == 2 ? lowest
32752 : (highest + lowest) / 2)
32753 - (nrefy == 0 ? ascent + descent
32754 : nrefy == 1 ? descent - boff
32755 : nrefy == 2 ? 0
32756 : (ascent + descent) / 2)
32757 + yoff);
32758 }
32759
32760 cmp->offsets[i * 2] = left;
32761 cmp->offsets[i * 2 + 1] = btm + descent;
32762
32763
32764 if (width > 0)
32765 {
32766 right = left + width;
32767 if (left < leftmost)
32768 leftmost = left;
32769 if (right > rightmost)
32770 rightmost = right;
32771 }
32772 top = btm + descent + ascent;
32773 if (top > highest)
32774 highest = top;
32775 if (btm < lowest)
32776 lowest = btm;
32777
32778 if (cmp->lbearing > left + lbearing)
32779 cmp->lbearing = left + lbearing;
32780 if (cmp->rbearing < left + rbearing)
32781 cmp->rbearing = left + rbearing;
32782 }
32783 }
32784
32785
32786
32787
32788 if (leftmost < 0)
32789 {
32790 for (i = 0; i < cmp->glyph_len; i++)
32791 cmp->offsets[i * 2] -= leftmost;
32792 rightmost -= leftmost;
32793 cmp->lbearing -= leftmost;
32794 cmp->rbearing -= leftmost;
32795 }
32796
32797 if (left_padded && cmp->lbearing < 0)
32798 {
32799 for (i = 0; i < cmp->glyph_len; i++)
32800 cmp->offsets[i * 2] -= cmp->lbearing;
32801 rightmost -= cmp->lbearing;
32802 cmp->rbearing -= cmp->lbearing;
32803 cmp->lbearing = 0;
32804 }
32805 if (right_padded && rightmost < cmp->rbearing)
32806 {
32807 rightmost = cmp->rbearing;
32808 }
32809
32810 cmp->pixel_width = rightmost;
32811 cmp->ascent = highest;
32812 cmp->descent = - lowest;
32813 if (cmp->ascent < font_ascent)
32814 cmp->ascent = font_ascent;
32815 if (cmp->descent < font_descent)
32816 cmp->descent = font_descent;
32817 }
32818
32819 if (it->glyph_row
32820 && (cmp->lbearing < 0
32821 || cmp->rbearing > cmp->pixel_width))
32822 it->glyph_row->contains_overlapping_glyphs_p = true;
32823
32824 it->pixel_width = cmp->pixel_width;
32825 it->ascent = it->phys_ascent = cmp->ascent;
32826 it->descent = it->phys_descent = cmp->descent;
32827 IT_APPLY_FACE_BOX(it, face);
32828
32829
32830
32831 if (face->overline_p)
32832 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32833
32834 take_vertical_position_into_account (it);
32835 if (it->ascent < 0)
32836 it->ascent = 0;
32837 if (it->descent < 0)
32838 it->descent = 0;
32839
32840 if (it->glyph_row && cmp->glyph_len > 0)
32841 append_composite_glyph (it);
32842 }
32843 else if (it->what == IT_COMPOSITION)
32844 {
32845
32846 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32847 Lisp_Object gstring;
32848 struct font_metrics metrics;
32849
32850 it->nglyphs = 1;
32851
32852 gstring = composition_gstring_from_id (it->cmp_it.id);
32853 it->pixel_width
32854 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32855 &metrics);
32856 if (it->pixel_width == 0)
32857 {
32858 it->glyph_not_available_p = true;
32859 it->phys_ascent = it->ascent;
32860 it->phys_descent = it->descent;
32861 it->pixel_width = face->font->space_width;
32862 }
32863 else
32864 {
32865 if (it->glyph_row
32866 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32867 it->glyph_row->contains_overlapping_glyphs_p = true;
32868 it->ascent = it->phys_ascent = metrics.ascent;
32869 it->descent = it->phys_descent = metrics.descent;
32870 }
32871 IT_APPLY_FACE_BOX(it, face);
32872
32873
32874
32875 if (face->overline_p)
32876 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32877 take_vertical_position_into_account (it);
32878 if (it->ascent < 0)
32879 it->ascent = 0;
32880 if (it->descent < 0)
32881 it->descent = 0;
32882
32883 if (it->glyph_row)
32884 append_composite_glyph (it);
32885 }
32886 else if (it->what == IT_GLYPHLESS)
32887 produce_glyphless_glyph (it, false, Qnil);
32888 else if (it->what == IT_IMAGE)
32889 produce_image_glyph (it);
32890 else if (it->what == IT_STRETCH)
32891 produce_stretch_glyph (it);
32892 else if (it->what == IT_XWIDGET)
32893 produce_xwidget_glyph (it);
32894
32895 done:
32896
32897
32898 eassert (it->ascent >= 0 && it->descent >= 0);
32899 if (it->area == TEXT_AREA)
32900 it->current_x += it->pixel_width;
32901
32902 if (extra_line_spacing > 0)
32903 {
32904 it->descent += extra_line_spacing;
32905 if (extra_line_spacing > it->max_extra_line_spacing)
32906 it->max_extra_line_spacing = extra_line_spacing;
32907 }
32908
32909 it->max_ascent = max (it->max_ascent, it->ascent);
32910 it->max_descent = max (it->max_descent, it->descent);
32911 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32912 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32913 }
32914
32915
32916
32917
32918
32919
32920 void
32921 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32922 struct glyph *start, enum glyph_row_area updated_area, int len)
32923 {
32924 int x, hpos, chpos = w->phys_cursor.hpos;
32925
32926 eassert (updated_row);
32927
32928
32929
32930 if (!updated_row->reversed_p && chpos < 0)
32931 chpos = 0;
32932 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
32933 chpos = updated_row->used[TEXT_AREA] - 1;
32934
32935 block_input ();
32936
32937
32938
32939 hpos = start - updated_row->glyphs[updated_area];
32940 x = draw_glyphs (w, w->output_cursor.x,
32941 updated_row, updated_area,
32942 hpos, hpos + len,
32943 DRAW_NORMAL_TEXT, 0);
32944
32945
32946 if (updated_area == TEXT_AREA
32947 && w->phys_cursor_on_p
32948 && w->phys_cursor.vpos == w->output_cursor.vpos
32949 && chpos >= hpos
32950 && chpos < hpos + len)
32951 w->phys_cursor_on_p = false;
32952
32953 unblock_input ();
32954
32955
32956 w->output_cursor.hpos += len;
32957 w->output_cursor.x = x;
32958 }
32959
32960
32961
32962
32963
32964 void
32965 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
32966 struct glyph *start, enum glyph_row_area updated_area, int len)
32967 {
32968 struct frame *f;
32969 int line_height, shift_by_width, shifted_region_width;
32970 struct glyph_row *row;
32971 struct glyph *glyph;
32972 int frame_x, frame_y;
32973 ptrdiff_t hpos;
32974
32975 eassert (updated_row);
32976 block_input ();
32977 f = XFRAME (WINDOW_FRAME (w));
32978
32979
32980 row = updated_row;
32981 line_height = row->height;
32982
32983
32984 shift_by_width = 0;
32985 for (glyph = start; glyph < start + len; ++glyph)
32986 shift_by_width += glyph->pixel_width;
32987
32988
32989 shifted_region_width = (window_box_width (w, updated_area)
32990 - w->output_cursor.x
32991 - shift_by_width);
32992
32993
32994 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
32995 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
32996
32997 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
32998 line_height, shift_by_width);
32999
33000
33001 hpos = start - row->glyphs[updated_area];
33002 draw_glyphs (w, w->output_cursor.x, row, updated_area,
33003 hpos, hpos + len,
33004 DRAW_NORMAL_TEXT, 0);
33005
33006
33007 w->output_cursor.hpos += len;
33008 w->output_cursor.x += shift_by_width;
33009 unblock_input ();
33010 }
33011
33012
33013
33014
33015
33016
33017
33018
33019
33020
33021 void
33022 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
33023 enum glyph_row_area updated_area, int to_x)
33024 {
33025 struct frame *f;
33026 int max_x, min_y, max_y;
33027 int from_x, from_y, to_y;
33028 struct face *face;
33029
33030 eassert (updated_row);
33031 f = XFRAME (w->frame);
33032 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
33033
33034 if (updated_row->full_width_p)
33035 max_x = (WINDOW_PIXEL_WIDTH (w)
33036 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
33037 else
33038 max_x = window_box_width (w, updated_area);
33039 max_y = window_text_bottom_y (w);
33040
33041
33042
33043 if (to_x == 0)
33044 return;
33045 else if (to_x < 0)
33046 to_x = max_x;
33047 else
33048 to_x = min (to_x, max_x);
33049
33050 to_y = min (max_y, w->output_cursor.y + updated_row->height);
33051
33052
33053 if (!updated_row->full_width_p)
33054 notice_overwritten_cursor (w, updated_area,
33055 w->output_cursor.x, -1,
33056 updated_row->y,
33057 MATRIX_ROW_BOTTOM_Y (updated_row));
33058
33059 from_x = w->output_cursor.x;
33060
33061
33062 if (updated_row->full_width_p)
33063 {
33064 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
33065 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
33066 }
33067 else
33068 {
33069 int area_left = window_box_left (w, updated_area);
33070 from_x += area_left;
33071 to_x += area_left;
33072 }
33073
33074 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
33075 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
33076 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
33077
33078
33079 if (to_x > from_x && to_y > from_y)
33080 {
33081 block_input ();
33082 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
33083 to_x - from_x, to_y - from_y);
33084
33085 if (face && !updated_row->stipple_p)
33086 updated_row->stipple_p = face->stipple;
33087 unblock_input ();
33088 }
33089 }
33090
33091 #endif
33092
33093
33094
33095
33096
33097
33098
33099
33100
33101
33102
33103 static enum text_cursor_kinds
33104 get_specified_cursor_type (Lisp_Object arg, int *width)
33105 {
33106 enum text_cursor_kinds type;
33107
33108 if (NILP (arg))
33109 return NO_CURSOR;
33110
33111 if (EQ (arg, Qbox))
33112 return FILLED_BOX_CURSOR;
33113
33114 if (EQ (arg, Qhollow))
33115 return HOLLOW_BOX_CURSOR;
33116
33117 if (EQ (arg, Qbar))
33118 {
33119 *width = 2;
33120 return BAR_CURSOR;
33121 }
33122
33123 if (EQ (arg, Qhbar))
33124 {
33125 *width = 2;
33126 return HBAR_CURSOR;
33127 }
33128
33129 if (CONSP (arg)
33130 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
33131 {
33132 *width = XFIXNUM (XCDR (arg));
33133
33134 if (EQ (XCAR (arg), Qbox))
33135 return FILLED_BOX_CURSOR;
33136 else if (EQ (XCAR (arg), Qbar))
33137 return BAR_CURSOR;
33138 else if (EQ (XCAR (arg), Qhbar))
33139 return HBAR_CURSOR;
33140 }
33141
33142
33143
33144
33145 type = HOLLOW_BOX_CURSOR;
33146
33147 return type;
33148 }
33149
33150
33151 void
33152 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
33153 {
33154 int width = 1;
33155 Lisp_Object tem;
33156
33157 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
33158 FRAME_CURSOR_WIDTH (f) = width;
33159
33160
33161
33162 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
33163 if (!NILP (tem))
33164 {
33165 FRAME_BLINK_OFF_CURSOR (f)
33166 = get_specified_cursor_type (XCDR (tem), &width);
33167 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
33168 }
33169 else
33170 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
33171
33172
33173 f->cursor_type_changed = true;
33174 }
33175
33176
33177 #ifdef HAVE_WINDOW_SYSTEM
33178
33179
33180
33181
33182
33183
33184
33185
33186
33187
33188
33189
33190 static enum text_cursor_kinds
33191 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
33192 bool *active_cursor)
33193 {
33194 struct frame *f = XFRAME (w->frame);
33195 struct buffer *b = XBUFFER (w->contents);
33196 int cursor_type = DEFAULT_CURSOR;
33197 Lisp_Object alt_cursor;
33198 bool non_selected = false;
33199
33200 *active_cursor = true;
33201
33202
33203 if (cursor_in_echo_area
33204 && FRAME_HAS_MINIBUF_P (f)
33205 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
33206 {
33207 if (w == XWINDOW (echo_area_window))
33208 {
33209 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
33210 {
33211 *width = FRAME_CURSOR_WIDTH (f);
33212 return FRAME_DESIRED_CURSOR (f);
33213 }
33214 else
33215 return get_specified_cursor_type (BVAR (b, cursor_type), width);
33216 }
33217
33218 *active_cursor = false;
33219 non_selected = true;
33220 }
33221
33222
33223 else if (w != XWINDOW (f->selected_window)
33224 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
33225 {
33226 *active_cursor = false;
33227
33228 if (MINI_WINDOW_P (w) &&
33229 (minibuf_level == 0
33230 || is_minibuffer (0, w->contents)))
33231 return NO_CURSOR;
33232
33233 non_selected = true;
33234 }
33235
33236
33237 if (NILP (BVAR (b, cursor_type)))
33238 return NO_CURSOR;
33239
33240
33241 if (EQ (BVAR (b, cursor_type), Qt))
33242 {
33243 cursor_type = FRAME_DESIRED_CURSOR (f);
33244 *width = FRAME_CURSOR_WIDTH (f);
33245 }
33246 else
33247 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
33248
33249
33250
33251 if (non_selected)
33252 {
33253 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
33254 if (!EQ (Qt, alt_cursor))
33255 return get_specified_cursor_type (alt_cursor, width);
33256
33257 if (cursor_type == FILLED_BOX_CURSOR)
33258 cursor_type = HOLLOW_BOX_CURSOR;
33259 else if (cursor_type == BAR_CURSOR && *width > 1)
33260 --*width;
33261 return cursor_type;
33262 }
33263
33264
33265 if (!w->cursor_off_p)
33266 {
33267 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
33268 return NO_CURSOR;
33269 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
33270 {
33271 if (cursor_type == FILLED_BOX_CURSOR)
33272 {
33273
33274
33275
33276
33277 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
33278 if (img != NULL && IMAGEP (img->spec))
33279 {
33280
33281
33282
33283
33284
33285
33286 if (!img->mask
33287 || (CONSP (BVAR (b, cursor_type))
33288 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33289 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33290 cursor_type = HOLLOW_BOX_CURSOR;
33291 }
33292 }
33293 else if (cursor_type != NO_CURSOR)
33294 {
33295
33296
33297
33298 cursor_type = HOLLOW_BOX_CURSOR;
33299 }
33300 }
33301 return cursor_type;
33302 }
33303
33304
33305
33306
33307 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33308 return get_specified_cursor_type (XCDR (alt_cursor), width);
33309
33310
33311 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33312 {
33313 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33314 return FRAME_BLINK_OFF_CURSOR (f);
33315 }
33316
33317 #if false
33318
33319
33320
33321
33322
33323
33324
33325
33326
33327
33328 if (cursor_type == FILLED_BOX_CURSOR)
33329 return HOLLOW_BOX_CURSOR;
33330
33331 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33332 {
33333 *width = 1;
33334 return cursor_type;
33335 }
33336 #endif
33337
33338 return NO_CURSOR;
33339 }
33340
33341
33342
33343
33344
33345
33346
33347
33348
33349 static void
33350 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33351 int x0, int x1, int y0, int y1)
33352 {
33353 int cx0, cx1, cy0, cy1;
33354 struct glyph_row *row;
33355
33356 if (!w->phys_cursor_on_p)
33357 return;
33358 if (area != TEXT_AREA)
33359 return;
33360
33361 if (w->phys_cursor.vpos < 0
33362 || w->phys_cursor.vpos >= w->current_matrix->nrows
33363 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33364 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33365 return;
33366
33367 if (row->cursor_in_fringe_p)
33368 {
33369 row->cursor_in_fringe_p = false;
33370 draw_fringe_bitmap (w, row, row->reversed_p);
33371 w->phys_cursor_on_p = false;
33372 return;
33373 }
33374
33375 cx0 = w->phys_cursor.x;
33376 cx1 = cx0 + w->phys_cursor_width;
33377 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33378 return;
33379
33380
33381
33382
33383
33384
33385
33386
33387
33388
33389
33390
33391
33392
33393
33394
33395
33396 cy0 = w->phys_cursor.y;
33397 cy1 = cy0 + w->phys_cursor_height;
33398 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33399 return;
33400
33401 w->phys_cursor_on_p = false;
33402 }
33403
33404 #endif
33405
33406
33407
33408
33409
33410
33411 #ifdef HAVE_WINDOW_SYSTEM
33412
33413
33414
33415
33416
33417 void
33418 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33419 enum glyph_row_area area, int overlaps)
33420 {
33421 int i, x;
33422
33423 block_input ();
33424
33425 x = 0;
33426 for (i = 0; i < row->used[area];)
33427 {
33428 if (row->glyphs[area][i].overlaps_vertically_p)
33429 {
33430 int start = i, start_x = x;
33431
33432 do
33433 {
33434 x += row->glyphs[area][i].pixel_width;
33435 ++i;
33436 }
33437 while (i < row->used[area]
33438 && row->glyphs[area][i].overlaps_vertically_p);
33439
33440 draw_glyphs (w, start_x, row, area,
33441 start, i,
33442 DRAW_NORMAL_TEXT, overlaps);
33443 }
33444 else
33445 {
33446 x += row->glyphs[area][i].pixel_width;
33447 ++i;
33448 }
33449 }
33450
33451 unblock_input ();
33452 }
33453
33454
33455
33456
33457
33458
33459 void
33460 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33461 enum draw_glyphs_face hl)
33462 {
33463
33464
33465
33466 if ((row->reversed_p
33467 ? (w->phys_cursor.hpos >= 0)
33468 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33469 {
33470 bool on_p = w->phys_cursor_on_p;
33471 int x1;
33472 int hpos = w->phys_cursor.hpos;
33473
33474
33475
33476
33477 if (!row->reversed_p && hpos < 0)
33478 hpos = 0;
33479 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33480 hpos = row->used[TEXT_AREA] - 1;
33481
33482 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33483 hl, 0);
33484 w->phys_cursor_on_p = on_p;
33485
33486 if (hl == DRAW_CURSOR)
33487 w->phys_cursor_width = x1 - w->phys_cursor.x;
33488
33489
33490
33491 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33492 {
33493 w->phys_cursor_width = x1 - w->phys_cursor.x;
33494
33495 if (row > w->current_matrix->rows
33496 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33497 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33498 OVERLAPS_ERASED_CURSOR);
33499
33500 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33501 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33502 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33503 OVERLAPS_ERASED_CURSOR);
33504 }
33505 }
33506 }
33507
33508
33509
33510
33511 void
33512 erase_phys_cursor (struct window *w)
33513 {
33514 struct frame *f = XFRAME (w->frame);
33515 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33516 int hpos = w->phys_cursor.hpos;
33517 int vpos = w->phys_cursor.vpos;
33518 bool mouse_face_here_p = false;
33519 struct glyph_matrix *active_glyphs = w->current_matrix;
33520 struct glyph_row *cursor_row;
33521 struct glyph *cursor_glyph;
33522 enum draw_glyphs_face hl;
33523
33524
33525
33526 if (w->phys_cursor_type == NO_CURSOR)
33527 goto mark_cursor_off;
33528
33529
33530
33531 if (vpos >= active_glyphs->nrows)
33532 goto mark_cursor_off;
33533
33534
33535
33536 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33537 if (!cursor_row->enabled_p)
33538 goto mark_cursor_off;
33539
33540
33541
33542 cursor_row->visible_height = min (cursor_row->visible_height,
33543 window_text_bottom_y (w) - cursor_row->y);
33544
33545
33546
33547
33548 if (cursor_row->visible_height <= 0)
33549 goto mark_cursor_off;
33550
33551
33552 if (cursor_row->cursor_in_fringe_p)
33553 {
33554 cursor_row->cursor_in_fringe_p = false;
33555 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33556 goto mark_cursor_off;
33557 }
33558
33559
33560
33561
33562
33563
33564 if ((cursor_row->reversed_p
33565 ? (w->phys_cursor.hpos < 0)
33566 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33567 goto mark_cursor_off;
33568
33569
33570
33571
33572 if (!cursor_row->reversed_p && hpos < 0)
33573 hpos = 0;
33574 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33575 hpos = cursor_row->used[TEXT_AREA] - 1;
33576
33577
33578
33579 if (! NILP (hlinfo->mouse_face_window)
33580 && coords_in_mouse_face_p (w, hpos, vpos)
33581
33582
33583
33584 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33585 mouse_face_here_p = true;
33586
33587 #ifdef HAVE_WINDOW_SYSTEM
33588
33589
33590
33591
33592 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33593 {
33594 w->phys_cursor_on_p = false;
33595 w->phys_cursor_type = NO_CURSOR;
33596 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33597 return;
33598 }
33599 #endif
33600
33601
33602 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33603 {
33604 int x, y;
33605 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33606 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33607 int width;
33608
33609 cursor_glyph = get_phys_cursor_glyph (w);
33610 if (cursor_glyph == NULL)
33611 goto mark_cursor_off;
33612
33613 width = cursor_glyph->pixel_width;
33614 x = w->phys_cursor.x;
33615 if (x < 0)
33616 {
33617 width += x;
33618 x = 0;
33619 }
33620 width = min (width, window_box_width (w, TEXT_AREA) - x);
33621 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33622 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33623
33624 if (width > 0)
33625 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33626 }
33627
33628
33629 if (mouse_face_here_p)
33630 hl = DRAW_MOUSE_FACE;
33631 else
33632 hl = DRAW_NORMAL_TEXT;
33633 draw_phys_cursor_glyph (w, cursor_row, hl);
33634
33635 mark_cursor_off:
33636 w->phys_cursor_on_p = false;
33637 w->phys_cursor_type = NO_CURSOR;
33638 }
33639
33640
33641
33642
33643
33644
33645 void
33646 display_and_set_cursor (struct window *w, bool on,
33647 int hpos, int vpos, int x, int y)
33648 {
33649 struct frame *f = XFRAME (w->frame);
33650 int new_cursor_type;
33651 int new_cursor_width UNINIT;
33652 bool active_cursor;
33653 struct glyph_row *glyph_row;
33654 struct glyph *glyph;
33655
33656
33657
33658
33659
33660 if (! FRAME_REDISPLAY_P (f)
33661 || vpos >= w->current_matrix->nrows
33662 || hpos >= w->current_matrix->matrix_w)
33663 return;
33664
33665
33666 if (!on && !w->phys_cursor_on_p)
33667 return;
33668
33669 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33670
33671
33672 if (!glyph_row->enabled_p)
33673 {
33674 w->phys_cursor_on_p = false;
33675 return;
33676 }
33677
33678
33679
33680
33681
33682
33683
33684
33685
33686 if (FRAME_GARBAGED_P (f))
33687 {
33688 if (on)
33689 {
33690 w->phys_cursor.x = x;
33691 w->phys_cursor.y = glyph_row->y;
33692 w->phys_cursor.hpos = hpos;
33693 w->phys_cursor.vpos = vpos;
33694 }
33695 return;
33696 }
33697
33698 glyph = NULL;
33699 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33700 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33701
33702 eassert (input_blocked_p ());
33703
33704
33705 new_cursor_type = get_window_cursor_type (w, glyph,
33706 &new_cursor_width, &active_cursor);
33707
33708
33709
33710
33711 if (w->phys_cursor_on_p
33712 && (!on
33713 || w->phys_cursor.x != x
33714 || w->phys_cursor.y != y
33715
33716
33717
33718 || hpos < 0
33719 || new_cursor_type != w->phys_cursor_type
33720 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33721 && new_cursor_width != w->phys_cursor_width)))
33722 erase_phys_cursor (w);
33723
33724
33725
33726
33727
33728
33729 if (on)
33730 {
33731 w->phys_cursor_ascent = glyph_row->ascent;
33732 w->phys_cursor_height = glyph_row->height;
33733
33734
33735
33736 w->phys_cursor.x = x;
33737 w->phys_cursor.y = glyph_row->y;
33738 w->phys_cursor.hpos = hpos;
33739 w->phys_cursor.vpos = vpos;
33740 }
33741
33742 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33743 new_cursor_type, new_cursor_width,
33744 on, active_cursor);
33745 }
33746
33747
33748
33749
33750
33751 static void
33752 update_window_cursor (struct window *w, bool on)
33753 {
33754
33755
33756 if (w->current_matrix)
33757 {
33758 int hpos = w->phys_cursor.hpos;
33759 int vpos = w->phys_cursor.vpos;
33760 struct glyph_row *row;
33761
33762 if (vpos >= w->current_matrix->nrows
33763 || hpos >= w->current_matrix->matrix_w)
33764 return;
33765
33766 row = MATRIX_ROW (w->current_matrix, vpos);
33767
33768
33769
33770
33771 if (!row->reversed_p && hpos < 0)
33772 hpos = 0;
33773 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33774 hpos = row->used[TEXT_AREA] - 1;
33775
33776 block_input ();
33777 display_and_set_cursor (w, on, hpos, vpos,
33778 w->phys_cursor.x, w->phys_cursor.y);
33779 unblock_input ();
33780 }
33781 }
33782
33783
33784
33785
33786
33787 static void
33788 update_cursor_in_window_tree (struct window *w, bool on_p)
33789 {
33790 while (w)
33791 {
33792 if (WINDOWP (w->contents))
33793 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33794 else
33795 update_window_cursor (w, on_p);
33796
33797 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33798 }
33799 }
33800
33801
33802
33803
33804
33805
33806 void
33807 gui_update_cursor (struct frame *f, bool on_p)
33808 {
33809 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33810 }
33811
33812
33813
33814
33815
33816
33817
33818 void
33819 gui_clear_cursor (struct window *w)
33820 {
33821 if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33822 update_window_cursor (w, false);
33823 }
33824
33825 #endif
33826
33827
33828
33829 static void
33830 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33831 int start_hpos, int end_hpos,
33832 enum draw_glyphs_face draw)
33833 {
33834 #ifdef HAVE_WINDOW_SYSTEM
33835 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33836 {
33837 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33838 return;
33839 }
33840 #endif
33841
33842 #ifndef HAVE_ANDROID
33843 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33844 #endif
33845 }
33846
33847
33848
33849 static void
33850 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33851 {
33852
33853
33854 if (!WINDOWP (hlinfo->mouse_face_window))
33855 return;
33856
33857 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33858 struct frame *f = XFRAME (WINDOW_FRAME (w));
33859
33860
33861 if (f != hlinfo->mouse_face_mouse_frame)
33862 return;
33863
33864 if (
33865
33866 w->current_matrix != NULL
33867
33868 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33869
33870
33871 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33872 {
33873 bool phys_cursor_on_p = w->phys_cursor_on_p;
33874 #ifdef HAVE_WINDOW_SYSTEM
33875 int mouse_off = 0;
33876 #endif
33877 struct glyph_row *row, *first, *last;
33878
33879 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33880 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33881
33882 for (row = first; row <= last && row->enabled_p; ++row)
33883 {
33884 int start_hpos, end_hpos, start_x;
33885
33886
33887 if (row == first)
33888 {
33889
33890
33891
33892
33893 if (!row->reversed_p)
33894 {
33895 start_hpos = hlinfo->mouse_face_beg_col;
33896 start_x = hlinfo->mouse_face_beg_x;
33897 }
33898 else if (row == last)
33899 {
33900 start_hpos = hlinfo->mouse_face_end_col;
33901 start_x = hlinfo->mouse_face_end_x;
33902 }
33903 else
33904 {
33905 start_hpos = 0;
33906 start_x = 0;
33907 }
33908 }
33909 else if (row->reversed_p && row == last)
33910 {
33911 start_hpos = hlinfo->mouse_face_end_col;
33912 start_x = hlinfo->mouse_face_end_x;
33913 }
33914 else
33915 {
33916 start_hpos = 0;
33917 start_x = 0;
33918 }
33919
33920 if (row == last)
33921 {
33922 if (!row->reversed_p)
33923 end_hpos = hlinfo->mouse_face_end_col;
33924 else if (row == first)
33925 end_hpos = hlinfo->mouse_face_beg_col;
33926 else
33927 {
33928 end_hpos = row->used[TEXT_AREA];
33929 if (draw == DRAW_NORMAL_TEXT)
33930 row->fill_line_p = true;
33931 }
33932 }
33933 else if (row->reversed_p && row == first)
33934 end_hpos = hlinfo->mouse_face_beg_col;
33935 else
33936 {
33937 end_hpos = row->used[TEXT_AREA];
33938 if (draw == DRAW_NORMAL_TEXT)
33939 row->fill_line_p = true;
33940 }
33941
33942 if (end_hpos > start_hpos)
33943 {
33944 draw_row_with_mouse_face (w, start_x, row,
33945 start_hpos, end_hpos, draw);
33946
33947 row->mouse_face_p
33948 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
33949 }
33950 #ifdef HAVE_WINDOW_SYSTEM
33951
33952 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
33953
33954
33955 && !w->pseudo_window_p
33956 && draw == DRAW_MOUSE_FACE)
33957 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
33958 #endif
33959 }
33960
33961
33962
33963 if (FRAME_WINDOW_P (f)
33964 && phys_cursor_on_p && !w->phys_cursor_on_p)
33965 {
33966 #ifdef HAVE_WINDOW_SYSTEM
33967 int hpos = w->phys_cursor.hpos;
33968 int old_phys_cursor_x = w->phys_cursor.x;
33969
33970
33971
33972
33973 if (!row->reversed_p && hpos < 0)
33974 hpos = 0;
33975 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33976 hpos = row->used[TEXT_AREA] - 1;
33977
33978 block_input ();
33979 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
33980 w->phys_cursor.x + mouse_off,
33981 w->phys_cursor.y);
33982
33983
33984 w->phys_cursor.x = old_phys_cursor_x;
33985 unblock_input ();
33986 #endif
33987 }
33988 }
33989
33990 #ifdef HAVE_WINDOW_SYSTEM
33991
33992 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
33993 {
33994 if (draw == DRAW_NORMAL_TEXT
33995 #ifndef HAVE_EXT_TOOL_BAR
33996 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
33997 #endif
33998 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
33999 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
34000 else
34001 if (draw == DRAW_MOUSE_FACE)
34002 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
34003 else
34004 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
34005 }
34006 #endif
34007 }
34008
34009
34010
34011
34012
34013
34014 bool
34015 clear_mouse_face (Mouse_HLInfo *hlinfo)
34016 {
34017 bool cleared
34018 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
34019 if (cleared)
34020 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
34021 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
34022 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
34023 hlinfo->mouse_face_window = Qnil;
34024 hlinfo->mouse_face_overlay = Qnil;
34025 return cleared;
34026 }
34027
34028
34029
34030 static bool
34031 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
34032 {
34033 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
34034
34035
34036 if (!(WINDOWP (hlinfo->mouse_face_window)
34037 && XWINDOW (hlinfo->mouse_face_window) == w))
34038 return false;
34039 if (vpos < hlinfo->mouse_face_beg_row
34040 || vpos > hlinfo->mouse_face_end_row)
34041 return false;
34042 if (vpos > hlinfo->mouse_face_beg_row
34043 && vpos < hlinfo->mouse_face_end_row)
34044 return true;
34045
34046 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
34047 {
34048 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34049 {
34050 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
34051 return true;
34052 }
34053 else if ((vpos == hlinfo->mouse_face_beg_row
34054 && hpos >= hlinfo->mouse_face_beg_col)
34055 || (vpos == hlinfo->mouse_face_end_row
34056 && hpos < hlinfo->mouse_face_end_col))
34057 return true;
34058 }
34059 else
34060 {
34061 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34062 {
34063 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
34064 return true;
34065 }
34066 else if ((vpos == hlinfo->mouse_face_beg_row
34067 && hpos <= hlinfo->mouse_face_beg_col)
34068 || (vpos == hlinfo->mouse_face_end_row
34069 && hpos > hlinfo->mouse_face_end_col))
34070 return true;
34071 }
34072 return false;
34073 }
34074
34075
34076
34077
34078
34079 bool
34080 cursor_in_mouse_face_p (struct window *w)
34081 {
34082 int vpos = w->phys_cursor.vpos;
34083
34084
34085
34086 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
34087 return false;
34088
34089 int hpos = w->phys_cursor.hpos;
34090 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
34091
34092
34093
34094
34095 if (!row->reversed_p && hpos < 0)
34096 hpos = 0;
34097 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
34098 hpos = row->used[TEXT_AREA] - 1;
34099
34100 return coords_in_mouse_face_p (w, hpos, vpos);
34101 }
34102
34103
34104
34105
34106
34107
34108
34109
34110
34111 static void
34112 rows_from_pos_range (struct window *w,
34113 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
34114 Lisp_Object disp_string,
34115 struct glyph_row **start, struct glyph_row **end)
34116 {
34117 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34118 int last_y = window_text_bottom_y (w);
34119 struct glyph_row *row;
34120
34121 *start = NULL;
34122 *end = NULL;
34123
34124 while (!first->enabled_p
34125 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
34126 first++;
34127
34128
34129 for (row = first;
34130 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
34131 row++)
34132 {
34133
34134
34135
34136 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
34137 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
34138
34139
34140
34141
34142 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
34143 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
34144 && !row->ends_at_zv_p
34145 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
34146 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
34147 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
34148 && !row->ends_at_zv_p
34149 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
34150 {
34151
34152
34153
34154
34155
34156
34157
34158
34159
34160
34161 struct glyph *g = row->glyphs[TEXT_AREA];
34162 struct glyph *e = g + row->used[TEXT_AREA];
34163
34164 while (g < e)
34165 {
34166 if (((BUFFERP (g->object) || NILP (g->object))
34167 && start_charpos <= g->charpos && g->charpos < end_charpos)
34168
34169
34170 || EQ (g->object, disp_string))
34171 *start = row;
34172 g++;
34173 }
34174 if (*start)
34175 break;
34176 }
34177 }
34178
34179
34180 if (!*start
34181
34182
34183 && !(row->enabled_p
34184 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
34185 row = first;
34186 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
34187 {
34188 struct glyph_row *next = row + 1;
34189 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
34190
34191 if (!next->enabled_p
34192 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
34193
34194
34195
34196 || (start_charpos < next_start
34197 && end_charpos < next_start)
34198 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
34199 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
34200 && !next->ends_at_zv_p
34201 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
34202 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
34203 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
34204 && !next->ends_at_zv_p
34205 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
34206 {
34207 *end = row;
34208 break;
34209 }
34210 else
34211 {
34212
34213
34214
34215 struct glyph *g = next->glyphs[TEXT_AREA];
34216 struct glyph *s = g;
34217 struct glyph *e = g + next->used[TEXT_AREA];
34218
34219 while (g < e)
34220 {
34221 if (((BUFFERP (g->object) || NILP (g->object))
34222 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
34223
34224
34225
34226
34227
34228 || (((!next->reversed_p && g == s)
34229 || (next->reversed_p && g == e - 1))
34230 && (g->charpos == end_charpos
34231
34232
34233 || (g->charpos == -1
34234 && !row->ends_at_zv_p
34235 && next_start == end_charpos)))))
34236
34237
34238 || EQ (g->object, disp_string))
34239 break;
34240 g++;
34241 }
34242 if (g == e)
34243 {
34244 *end = row;
34245 break;
34246 }
34247
34248
34249 else if (next->ends_at_zv_p)
34250 {
34251 *end = next;
34252 break;
34253 }
34254 }
34255 }
34256 }
34257
34258
34259
34260
34261
34262
34263
34264
34265
34266
34267 static void
34268 mouse_face_from_buffer_pos (Lisp_Object window,
34269 Mouse_HLInfo *hlinfo,
34270 ptrdiff_t mouse_charpos,
34271 ptrdiff_t start_charpos,
34272 ptrdiff_t end_charpos,
34273 Lisp_Object before_string,
34274 Lisp_Object after_string,
34275 Lisp_Object disp_string)
34276 {
34277 struct window *w = XWINDOW (window);
34278 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34279 struct glyph_row *r1, *r2;
34280 struct glyph *glyph, *end;
34281 ptrdiff_t ignore, pos;
34282 int x;
34283
34284 eassert (NILP (disp_string) || STRINGP (disp_string));
34285 eassert (NILP (before_string) || STRINGP (before_string));
34286 eassert (NILP (after_string) || STRINGP (after_string));
34287
34288
34289 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
34290 if (r1 == NULL)
34291 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34292
34293
34294 if (!NILP (before_string) || !NILP (disp_string))
34295 {
34296 struct glyph_row *prev;
34297 while ((prev = r1 - 1, prev >= first)
34298 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34299 && prev->used[TEXT_AREA] > 0)
34300 {
34301 struct glyph *beg = prev->glyphs[TEXT_AREA];
34302 glyph = beg + prev->used[TEXT_AREA];
34303 while (--glyph >= beg && NILP (glyph->object));
34304 if (glyph < beg
34305 || !(EQ (glyph->object, before_string)
34306 || EQ (glyph->object, disp_string)))
34307 break;
34308 r1 = prev;
34309 }
34310 }
34311 if (r2 == NULL)
34312 {
34313 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34314 hlinfo->mouse_face_past_end = true;
34315 }
34316 else if (!NILP (after_string))
34317 {
34318
34319 struct glyph_row *next;
34320 struct glyph_row *last
34321 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34322
34323 for (next = r2 + 1;
34324 next <= last
34325 && next->used[TEXT_AREA] > 0
34326 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34327 ++next)
34328 r2 = next;
34329 }
34330
34331
34332
34333
34334
34335 if (r1->y > r2->y)
34336 {
34337 struct glyph_row *tem = r2;
34338
34339 r2 = r1;
34340 r1 = tem;
34341 }
34342
34343 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34344 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34345
34346
34347
34348
34349
34350
34351
34352
34353
34354
34355
34356 if (!r1->reversed_p)
34357 {
34358
34359
34360 glyph = r1->glyphs[TEXT_AREA];
34361 end = glyph + r1->used[TEXT_AREA];
34362 x = r1->x;
34363
34364
34365 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34366 for (; glyph < end
34367 && NILP (glyph->object)
34368 && glyph->charpos < 0;
34369 ++glyph)
34370 x += glyph->pixel_width;
34371
34372
34373
34374
34375 for (; glyph < end
34376 && !NILP (glyph->object)
34377 && !EQ (glyph->object, disp_string)
34378 && !(BUFFERP (glyph->object)
34379 && (glyph->charpos >= start_charpos
34380 && glyph->charpos < end_charpos));
34381 ++glyph)
34382 {
34383
34384
34385
34386 if (EQ (glyph->object, before_string))
34387 {
34388 pos = string_buffer_position (before_string,
34389 start_charpos);
34390
34391
34392 if (!pos || (pos >= start_charpos && pos < end_charpos))
34393 break;
34394 }
34395 else if (EQ (glyph->object, after_string))
34396 {
34397 pos = string_buffer_position (after_string, end_charpos);
34398 if (!pos || (pos >= start_charpos && pos < end_charpos))
34399 break;
34400 }
34401 x += glyph->pixel_width;
34402 }
34403 hlinfo->mouse_face_beg_x = x;
34404 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34405 }
34406 else
34407 {
34408
34409
34410 struct glyph *g;
34411
34412 end = r1->glyphs[TEXT_AREA] - 1;
34413 glyph = end + r1->used[TEXT_AREA];
34414
34415
34416 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34417 for (; glyph > end
34418 && NILP (glyph->object)
34419 && glyph->charpos < 0;
34420 --glyph)
34421 ;
34422
34423
34424
34425
34426 for (; glyph > end
34427 && !NILP (glyph->object)
34428 && !EQ (glyph->object, disp_string)
34429 && !(BUFFERP (glyph->object)
34430 && (glyph->charpos >= start_charpos
34431 && glyph->charpos < end_charpos));
34432 --glyph)
34433 {
34434
34435
34436
34437 if (EQ (glyph->object, before_string))
34438 {
34439 pos = string_buffer_position (before_string, start_charpos);
34440
34441
34442 if (!pos || (pos >= start_charpos && pos < end_charpos))
34443 break;
34444 }
34445 else if (EQ (glyph->object, after_string))
34446 {
34447 pos = string_buffer_position (after_string, end_charpos);
34448 if (!pos || (pos >= start_charpos && pos < end_charpos))
34449 break;
34450 }
34451 }
34452
34453 glyph++;
34454 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34455 x += g->pixel_width;
34456 hlinfo->mouse_face_beg_x = x;
34457 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34458 }
34459
34460
34461
34462
34463 if (r2 != r1)
34464 {
34465 if (!r2->reversed_p)
34466 {
34467 glyph = r2->glyphs[TEXT_AREA];
34468 end = glyph + r2->used[TEXT_AREA];
34469 x = r2->x;
34470 }
34471 else
34472 {
34473 end = r2->glyphs[TEXT_AREA] - 1;
34474 glyph = end + r2->used[TEXT_AREA];
34475 }
34476 }
34477
34478 if (!r2->reversed_p)
34479 {
34480
34481
34482
34483 while (end > glyph
34484 && NILP ((end - 1)->object))
34485 --end;
34486
34487
34488
34489
34490 for (--end;
34491 end > glyph
34492 && !NILP (end->object)
34493 && !EQ (end->object, disp_string)
34494 && !(BUFFERP (end->object)
34495 && (end->charpos >= start_charpos
34496 && end->charpos < end_charpos));
34497 --end)
34498 {
34499
34500
34501
34502 if (EQ (end->object, before_string))
34503 {
34504 pos = string_buffer_position (before_string, start_charpos);
34505 if (!pos || (pos >= start_charpos && pos < end_charpos))
34506 break;
34507 }
34508 else if (EQ (end->object, after_string))
34509 {
34510 pos = string_buffer_position (after_string, end_charpos);
34511 if (!pos || (pos >= start_charpos && pos < end_charpos))
34512 break;
34513 }
34514 }
34515
34516 for (; glyph <= end; ++glyph)
34517 x += glyph->pixel_width;
34518
34519 hlinfo->mouse_face_end_x = x;
34520 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34521 }
34522 else
34523 {
34524
34525
34526
34527 x = r2->x;
34528 end++;
34529 while (end < glyph
34530 && NILP (end->object))
34531 {
34532 x += end->pixel_width;
34533 ++end;
34534 }
34535
34536
34537
34538
34539 for ( ;
34540 end < glyph
34541 && !NILP (end->object)
34542 && !EQ (end->object, disp_string)
34543 && !(BUFFERP (end->object)
34544 && (end->charpos >= start_charpos
34545 && end->charpos < end_charpos));
34546 ++end)
34547 {
34548
34549
34550
34551 if (EQ (end->object, before_string))
34552 {
34553 pos = string_buffer_position (before_string, start_charpos);
34554 if (!pos || (pos >= start_charpos && pos < end_charpos))
34555 break;
34556 }
34557 else if (EQ (end->object, after_string))
34558 {
34559 pos = string_buffer_position (after_string, end_charpos);
34560 if (!pos || (pos >= start_charpos && pos < end_charpos))
34561 break;
34562 }
34563 x += end->pixel_width;
34564 }
34565
34566
34567
34568
34569
34570 if (end == glyph
34571 && BUFFERP (end->object)
34572 && (end->charpos < start_charpos
34573 || end->charpos >= end_charpos))
34574 {
34575 x += end->pixel_width;
34576 ++end;
34577 }
34578 hlinfo->mouse_face_end_x = x;
34579 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34580 }
34581
34582 hlinfo->mouse_face_window = window;
34583 hlinfo->mouse_face_face_id
34584 = face_at_buffer_position (w, mouse_charpos, &ignore,
34585 mouse_charpos + 1,
34586 !hlinfo->mouse_face_hidden, -1, 0);
34587 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34588 }
34589
34590
34591
34592
34593
34594 #if false
34595
34596
34597
34598
34599
34600
34601
34602
34603
34604
34605
34606
34607
34608
34609
34610
34611 static bool
34612 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34613 int *hpos, int *vpos, int *x, int *y, bool right_p)
34614 {
34615 int yb = window_text_bottom_y (w);
34616 struct glyph_row *r;
34617 struct glyph *best_glyph = NULL;
34618 struct glyph_row *best_row = NULL;
34619 int best_x = 0;
34620
34621 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34622 r->enabled_p && r->y < yb;
34623 ++r)
34624 {
34625 struct glyph *g = r->glyphs[TEXT_AREA];
34626 struct glyph *e = g + r->used[TEXT_AREA];
34627 int gx;
34628
34629 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34630 if (EQ (g->object, object))
34631 {
34632 if (g->charpos == pos)
34633 {
34634 best_glyph = g;
34635 best_x = gx;
34636 best_row = r;
34637 goto found;
34638 }
34639 else if (best_glyph == NULL
34640 || ((eabs (g->charpos - pos)
34641 < eabs (best_glyph->charpos - pos))
34642 && (right_p
34643 ? g->charpos < pos
34644 : g->charpos > pos)))
34645 {
34646 best_glyph = g;
34647 best_x = gx;
34648 best_row = r;
34649 }
34650 }
34651 }
34652
34653 found:
34654
34655 if (best_glyph)
34656 {
34657 *x = best_x;
34658 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34659
34660 if (right_p)
34661 {
34662 *x += best_glyph->pixel_width;
34663 ++*hpos;
34664 }
34665
34666 *y = best_row->y;
34667 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34668 }
34669
34670 return best_glyph != NULL;
34671 }
34672 #endif
34673
34674
34675
34676
34677
34678
34679 static void
34680 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34681 Lisp_Object object,
34682 ptrdiff_t startpos, ptrdiff_t endpos)
34683 {
34684 int yb = window_text_bottom_y (w);
34685 struct glyph_row *r;
34686 struct glyph *g, *e;
34687 int gx;
34688 bool found = false;
34689
34690
34691
34692
34693 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34694 r->enabled_p && r->y < yb;
34695 ++r)
34696 {
34697 if (!r->reversed_p)
34698 {
34699 g = r->glyphs[TEXT_AREA];
34700 e = g + r->used[TEXT_AREA];
34701 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34702 if (EQ (g->object, object)
34703 && startpos <= g->charpos && g->charpos < endpos)
34704 {
34705 hlinfo->mouse_face_beg_row
34706 = MATRIX_ROW_VPOS (r, w->current_matrix);
34707 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34708 hlinfo->mouse_face_beg_x = gx;
34709 found = true;
34710 break;
34711 }
34712 }
34713 else
34714 {
34715 struct glyph *g1;
34716
34717 e = r->glyphs[TEXT_AREA];
34718 g = e + r->used[TEXT_AREA];
34719 for ( ; g > e; --g)
34720 if (EQ ((g-1)->object, object)
34721 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34722 {
34723 hlinfo->mouse_face_beg_row
34724 = MATRIX_ROW_VPOS (r, w->current_matrix);
34725 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34726 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34727 gx += g1->pixel_width;
34728 hlinfo->mouse_face_beg_x = gx;
34729 found = true;
34730 break;
34731 }
34732 }
34733 if (found)
34734 break;
34735 }
34736
34737 if (!found)
34738 return;
34739
34740
34741
34742 for (++r; r->enabled_p && r->y < yb; ++r)
34743 {
34744 g = r->glyphs[TEXT_AREA];
34745 e = g + r->used[TEXT_AREA];
34746 found = false;
34747 for ( ; g < e; ++g)
34748 if (EQ (g->object, object)
34749 && startpos <= g->charpos && g->charpos < endpos)
34750 {
34751 found = true;
34752 break;
34753 }
34754 if (!found)
34755 break;
34756 }
34757
34758
34759 r--;
34760
34761
34762 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34763
34764
34765
34766 if (!r->reversed_p)
34767 {
34768 g = r->glyphs[TEXT_AREA];
34769 e = g + r->used[TEXT_AREA];
34770 for ( ; e > g; --e)
34771 if (EQ ((e-1)->object, object)
34772 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34773 break;
34774 hlinfo->mouse_face_end_col = e - g;
34775
34776 for (gx = r->x; g < e; ++g)
34777 gx += g->pixel_width;
34778 hlinfo->mouse_face_end_x = gx;
34779 }
34780 else
34781 {
34782 e = r->glyphs[TEXT_AREA];
34783 g = e + r->used[TEXT_AREA];
34784 for (gx = r->x ; e < g; ++e)
34785 {
34786 if (EQ (e->object, object)
34787 && startpos <= e->charpos && e->charpos < endpos)
34788 break;
34789 gx += e->pixel_width;
34790 }
34791 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34792 hlinfo->mouse_face_end_x = gx;
34793 }
34794 }
34795
34796 #ifdef HAVE_WINDOW_SYSTEM
34797
34798
34799
34800 static bool
34801 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34802 {
34803 if (!CONSP (hot_spot))
34804 return false;
34805
34806 if (EQ (XCAR (hot_spot), Qrect))
34807 {
34808
34809 Lisp_Object rect = XCDR (hot_spot);
34810 Lisp_Object tem;
34811 if (!CONSP (rect))
34812 return false;
34813 if (!CONSP (XCAR (rect)))
34814 return false;
34815 if (!CONSP (XCDR (rect)))
34816 return false;
34817 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34818 return false;
34819 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34820 return false;
34821 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34822 return false;
34823 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34824 return false;
34825 return true;
34826 }
34827 else if (EQ (XCAR (hot_spot), Qcircle))
34828 {
34829
34830 Lisp_Object circ = XCDR (hot_spot);
34831 Lisp_Object lr, lx0, ly0;
34832 if (CONSP (circ)
34833 && CONSP (XCAR (circ))
34834 && (lr = XCDR (circ), NUMBERP (lr))
34835 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34836 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34837 {
34838 double r = XFLOATINT (lr);
34839 double dx = XFIXNUM (lx0) - x;
34840 double dy = XFIXNUM (ly0) - y;
34841 return (dx * dx + dy * dy <= r * r);
34842 }
34843 }
34844 else if (EQ (XCAR (hot_spot), Qpoly))
34845 {
34846
34847 if (VECTORP (XCDR (hot_spot)))
34848 {
34849 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34850 Lisp_Object *poly = v->contents;
34851 ptrdiff_t n = v->header.size;
34852 ptrdiff_t i;
34853 bool inside = false;
34854 Lisp_Object lx, ly;
34855 int x0, y0;
34856
34857
34858 if (n < 6 || n & 1)
34859 return false;
34860
34861
34862
34863
34864
34865 if ((lx = poly[n-2], !FIXNUMP (lx))
34866 || (ly = poly[n-1], !FIXNUMP (lx)))
34867 return false;
34868 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34869 for (i = 0; i < n; i += 2)
34870 {
34871 int x1 = x0, y1 = y0;
34872 if ((lx = poly[i], !FIXNUMP (lx))
34873 || (ly = poly[i+1], !FIXNUMP (ly)))
34874 return false;
34875 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34876
34877
34878 if (x0 >= x)
34879 {
34880 if (x1 >= x)
34881 continue;
34882 }
34883 else if (x1 < x)
34884 continue;
34885 if (y > y0 && y > y1)
34886 continue;
34887 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34888 inside = !inside;
34889 }
34890 return inside;
34891 }
34892 }
34893 return false;
34894 }
34895
34896 Lisp_Object
34897 find_hot_spot (Lisp_Object map, int x, int y)
34898 {
34899 while (CONSP (map))
34900 {
34901 if (CONSP (XCAR (map))
34902 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34903 return XCAR (map);
34904 map = XCDR (map);
34905 }
34906
34907 return Qnil;
34908 }
34909
34910 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34911 3, 3, 0,
34912 doc:
34913
34914
34915
34916
34917
34918
34919
34920
34921 )
34922 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
34923 {
34924 if (NILP (map))
34925 return Qnil;
34926
34927 CHECK_FIXNUM (x);
34928 CHECK_FIXNUM (y);
34929
34930 return find_hot_spot (map,
34931 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
34932 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
34933 }
34934 #endif
34935
34936
34937
34938 static void
34939 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
34940 {
34941 #ifdef HAVE_WINDOW_SYSTEM
34942 if (!FRAME_WINDOW_P (f))
34943 return;
34944
34945
34946 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
34947 || EQ (track_mouse, Qdrag_source))
34948 return;
34949
34950 if (!NILP (pointer))
34951 {
34952 if (EQ (pointer, Qarrow))
34953 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34954 else if (EQ (pointer, Qhand))
34955 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34956 else if (EQ (pointer, Qtext))
34957 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
34958 else if (EQ (pointer, intern ("hdrag")))
34959 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
34960 else if (EQ (pointer, intern ("nhdrag")))
34961 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34962 # ifdef HAVE_X_WINDOWS
34963 else if (EQ (pointer, intern ("vdrag")))
34964 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
34965 # endif
34966 else if (EQ (pointer, intern ("hourglass")))
34967 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
34968 else if (EQ (pointer, Qmodeline))
34969 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
34970 else
34971 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34972 }
34973
34974 if (cursor != No_Cursor)
34975 FRAME_RIF (f)->define_frame_cursor (f, cursor);
34976 #endif
34977 }
34978
34979
34980
34981
34982
34983
34984
34985 static void
34986 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
34987 enum window_part area)
34988 {
34989 struct window *w = XWINDOW (window);
34990 struct frame *f = XFRAME (w->frame);
34991 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
34992 Emacs_Cursor cursor = No_Cursor;
34993 Lisp_Object pointer = Qnil;
34994 int dx, dy, width, height;
34995 ptrdiff_t charpos;
34996 Lisp_Object string, object = Qnil;
34997 Lisp_Object pos UNINIT;
34998 Lisp_Object mouse_face;
34999 int original_x_pixel = x;
35000 struct glyph * glyph = NULL, * row_start_glyph = NULL;
35001 struct glyph_row *row UNINIT;
35002
35003 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
35004 {
35005 int x0;
35006 struct glyph *end;
35007
35008
35009
35010 string = mode_line_string (w, area, &x, &y, &charpos,
35011 &object, &dx, &dy, &width, &height);
35012
35013 row = (area == ON_MODE_LINE
35014 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
35015 : (area == ON_TAB_LINE
35016 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
35017 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
35018
35019
35020 if (row->mode_line_p && row->enabled_p)
35021 {
35022 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
35023 end = glyph + row->used[TEXT_AREA];
35024
35025 for (x0 = original_x_pixel;
35026 glyph < end && x0 >= glyph->pixel_width;
35027 ++glyph)
35028 x0 -= glyph->pixel_width;
35029
35030 if (glyph >= end)
35031 glyph = NULL;
35032 }
35033 }
35034 else
35035 {
35036 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
35037
35038
35039 string = marginal_area_string (w, area, &x, &y, &charpos,
35040 &object, &dx, &dy, &width, &height);
35041 }
35042
35043 Lisp_Object help = Qnil;
35044
35045 #ifdef HAVE_WINDOW_SYSTEM
35046 if (IMAGEP (object))
35047 {
35048 Lisp_Object image_map, hotspot;
35049 if ((image_map = plist_get (XCDR (object), QCmap),
35050 !NILP (image_map))
35051 && (hotspot = find_hot_spot (image_map, dx, dy),
35052 CONSP (hotspot))
35053 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35054 {
35055 Lisp_Object plist;
35056
35057
35058
35059
35060 hotspot = XCDR (hotspot);
35061 if (CONSP (hotspot)
35062 && (plist = XCAR (hotspot), CONSP (plist)))
35063 {
35064 pointer = plist_get (plist, Qpointer);
35065 if (NILP (pointer))
35066 pointer = Qhand;
35067 help = plist_get (plist, Qhelp_echo);
35068 if (!NILP (help))
35069 {
35070 help_echo_string = help;
35071 XSETWINDOW (help_echo_window, w);
35072 help_echo_object = w->contents;
35073 help_echo_pos = charpos;
35074 }
35075 }
35076 }
35077 if (NILP (pointer))
35078 pointer = plist_get (XCDR (object), QCpointer);
35079 }
35080 #endif
35081
35082
35083
35084
35085 if (STRINGP (string))
35086 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
35087
35088
35089
35090
35091
35092 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
35093 || area == ON_TAB_LINE)
35094 {
35095
35096
35097 if (NILP (help))
35098 {
35099 if (STRINGP (string))
35100 help = Fget_text_property (pos, Qhelp_echo, string);
35101
35102 if (!NILP (help))
35103 {
35104 help_echo_string = help;
35105 XSETWINDOW (help_echo_window, w);
35106 help_echo_object = string;
35107 help_echo_pos = charpos;
35108 }
35109 else if (area == ON_MODE_LINE
35110 && !NILP (w->mode_line_help_echo))
35111 {
35112 help_echo_string = w->mode_line_help_echo;
35113 XSETWINDOW (help_echo_window, w);
35114 help_echo_object = Qnil;
35115 help_echo_pos = -1;
35116 }
35117 }
35118
35119 #ifdef HAVE_WINDOW_SYSTEM
35120
35121 if (FRAME_WINDOW_P (f))
35122 {
35123 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
35124 || minibuf_level
35125 || NILP (Vresize_mini_windows));
35126
35127 if (STRINGP (string))
35128 {
35129 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35130
35131 if (NILP (pointer))
35132 pointer = Fget_text_property (pos, Qpointer, string);
35133
35134
35135 if (NILP (pointer)
35136 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
35137 || area == ON_TAB_LINE))
35138 {
35139 Lisp_Object map;
35140
35141 map = Fget_text_property (pos, Qlocal_map, string);
35142 if (!KEYMAPP (map))
35143 map = Fget_text_property (pos, Qkeymap, string);
35144 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
35145 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35146 }
35147 }
35148 else if (draggable && area == ON_MODE_LINE)
35149 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35150 else if ((area == ON_MODE_LINE
35151 && WINDOW_BOTTOMMOST_P (w)
35152 && !FRAME_HAS_MINIBUF_P (f)
35153 && !NILP (Fframe_parameter
35154 (w->frame, Qdrag_with_mode_line)))
35155 || (((area == ON_HEADER_LINE
35156 && !NILP (Fframe_parameter
35157 (w->frame, Qdrag_with_header_line)))
35158 || (area == ON_TAB_LINE
35159 && !NILP (Fframe_parameter
35160 (w->frame, Qdrag_with_tab_line))))
35161 && WINDOW_TOPMOST_P (w)))
35162 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35163 else
35164 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35165 }
35166 #endif
35167 }
35168
35169
35170 bool mouse_face_shown = false;
35171
35172 if (STRINGP (string))
35173 {
35174 mouse_face = Fget_text_property (pos, Qmouse_face, string);
35175 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
35176 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
35177 || (area == ON_TAB_LINE))
35178 && glyph)
35179 {
35180 Lisp_Object b, e;
35181
35182 struct glyph * tmp_glyph;
35183
35184 int gpos;
35185 int gseq_length;
35186 int total_pixel_width;
35187 ptrdiff_t begpos, endpos, ignore;
35188
35189 int vpos, hpos;
35190
35191 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
35192 Qmouse_face, string, Qnil);
35193 if (NILP (b))
35194 begpos = 0;
35195 else
35196 begpos = XFIXNUM (b);
35197
35198 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
35199 if (NILP (e))
35200 endpos = SCHARS (string);
35201 else
35202 endpos = XFIXNUM (e);
35203
35204
35205
35206
35207
35208
35209
35210
35211
35212
35213
35214 tmp_glyph = row_start_glyph;
35215 while (tmp_glyph < glyph
35216 && (!(EQ (tmp_glyph->object, glyph->object)
35217 && begpos <= tmp_glyph->charpos
35218 && tmp_glyph->charpos < endpos)))
35219 tmp_glyph++;
35220 gpos = glyph - tmp_glyph;
35221
35222
35223
35224
35225
35226
35227 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
35228 tmp_glyph > glyph
35229 && (!(EQ (tmp_glyph->object, glyph->object)
35230 && begpos <= tmp_glyph->charpos
35231 && tmp_glyph->charpos < endpos));
35232 tmp_glyph--)
35233 ;
35234 gseq_length = gpos + (tmp_glyph - glyph) + 1;
35235
35236
35237
35238 total_pixel_width = 0;
35239 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
35240 total_pixel_width += tmp_glyph->pixel_width;
35241
35242
35243
35244
35245 hpos = x - gpos;
35246 vpos = (area == ON_MODE_LINE
35247 ? (w->current_matrix)->nrows - 1
35248 : (area == ON_TAB_LINE
35249 ? 0
35250 : (w->current_matrix->tab_line_p
35251 ? 1
35252 : 0)));
35253
35254
35255
35256 if ( EQ (window, hlinfo->mouse_face_window)
35257 && (!row->reversed_p
35258 ? (hlinfo->mouse_face_beg_col <= hpos
35259 && hpos < hlinfo->mouse_face_end_col)
35260
35261 : (hlinfo->mouse_face_end_col <= hpos
35262 && hpos < hlinfo->mouse_face_beg_col))
35263 && hlinfo->mouse_face_beg_row == vpos )
35264 return;
35265
35266 if (clear_mouse_face (hlinfo))
35267 cursor = No_Cursor;
35268
35269 if (!row->reversed_p)
35270 {
35271 hlinfo->mouse_face_beg_col = hpos;
35272 hlinfo->mouse_face_beg_x = original_x_pixel
35273 - (total_pixel_width + dx);
35274 hlinfo->mouse_face_end_col = hpos + gseq_length;
35275 hlinfo->mouse_face_end_x = 0;
35276 }
35277 else
35278 {
35279
35280
35281 hlinfo->mouse_face_end_col = hpos;
35282 hlinfo->mouse_face_end_x = original_x_pixel
35283 - (total_pixel_width + dx);
35284 hlinfo->mouse_face_beg_col = hpos + gseq_length;
35285 hlinfo->mouse_face_beg_x = 0;
35286 }
35287
35288 hlinfo->mouse_face_beg_row = vpos;
35289 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
35290 hlinfo->mouse_face_past_end = false;
35291 hlinfo->mouse_face_window = window;
35292
35293 hlinfo->mouse_face_face_id =
35294 face_at_string_position (w, string, charpos, 0, &ignore,
35295 glyph->face_id, true, 0);
35296
35297 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35298 mouse_face_shown = true;
35299
35300 if (NILP (pointer))
35301 pointer = Qhand;
35302 }
35303 }
35304
35305
35306
35307 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35308 || area == ON_TAB_LINE) && !mouse_face_shown)
35309 clear_mouse_face (hlinfo);
35310
35311 define_frame_cursor1 (f, cursor, pointer);
35312 }
35313
35314
35315
35316
35317
35318
35319
35320
35321
35322
35323 void
35324 note_mouse_highlight (struct frame *f, int x, int y)
35325 {
35326 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35327 enum window_part part = ON_NOTHING;
35328 Lisp_Object window;
35329 struct window *w;
35330 Emacs_Cursor cursor = No_Cursor;
35331 Lisp_Object pointer = Qnil;
35332 struct buffer *b;
35333
35334
35335 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS) \
35336 || defined (HAVE_ANDROID)
35337 if (popup_activated ())
35338 return;
35339 #endif
35340
35341 #if defined (HAVE_HAIKU)
35342 if (popup_activated_p)
35343 return;
35344 #endif
35345
35346 if (!f->glyphs_initialized_p
35347 || f->pointer_invisible)
35348 return;
35349
35350 hlinfo->mouse_face_mouse_x = x;
35351 hlinfo->mouse_face_mouse_y = y;
35352 hlinfo->mouse_face_mouse_frame = f;
35353
35354 if (hlinfo->mouse_face_defer)
35355 return;
35356
35357
35358 window = window_from_coordinates (f, x, y, &part, true, true);
35359
35360
35361 if (! EQ (window, hlinfo->mouse_face_window)
35362
35363 || (!NILP (hlinfo->mouse_face_window)
35364 && !NILP (window)
35365 && part != ON_TEXT
35366 && part != ON_MODE_LINE
35367 && part != ON_HEADER_LINE
35368 && part != ON_TAB_LINE))
35369 clear_mouse_face (hlinfo);
35370
35371
35372 help_echo_string = Qnil;
35373
35374
35375 if (!FRAME_WINDOW_P (f)
35376 && (y >= FRAME_MENU_BAR_LINES (f)
35377 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35378 {
35379 int prop_idx;
35380 bool ignore;
35381 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35382
35383 if (!NILP (caption))
35384 {
35385 help_echo_object = help_echo_window = Qnil;
35386 help_echo_pos = -1;
35387 help_echo_string = AREF (f->tab_bar_items,
35388 prop_idx * TAB_BAR_ITEM_NSLOTS
35389 + TAB_BAR_ITEM_HELP);
35390 if (NILP (help_echo_string))
35391 help_echo_string = caption;
35392 }
35393 }
35394
35395 #ifdef HAVE_WINDOW_SYSTEM
35396
35397
35398 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35399 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35400 {
35401 enum internal_border_part part = frame_internal_border_part (f, x, y);
35402
35403 switch (part)
35404 {
35405 case INTERNAL_BORDER_NONE:
35406 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35407
35408 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35409 break;
35410 case INTERNAL_BORDER_LEFT_EDGE:
35411 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35412 break;
35413 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35414 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35415 break;
35416 case INTERNAL_BORDER_TOP_EDGE:
35417 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35418 break;
35419 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35420 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35421 break;
35422 case INTERNAL_BORDER_RIGHT_EDGE:
35423 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35424 break;
35425 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35426 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35427 break;
35428 case INTERNAL_BORDER_BOTTOM_EDGE:
35429 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35430 break;
35431 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35432 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35433 break;
35434 default:
35435
35436 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35437 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35438 }
35439
35440 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35441 {
35442
35443 help_echo_string = build_string ("drag-mouse-1: resize frame");
35444 goto set_cursor;
35445 }
35446 }
35447 #endif
35448
35449
35450 if (!WINDOWP (window))
35451 return;
35452
35453
35454 w = XWINDOW (window);
35455 frame_to_window_pixel_xy (w, &x, &y);
35456
35457 #if defined (HAVE_WINDOW_SYSTEM)
35458
35459
35460 if (EQ (window, f->tab_bar_window))
35461 {
35462 note_tab_bar_highlight (f, x, y);
35463 if (tab_bar__dragging_in_progress)
35464 {
35465 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35466 goto set_cursor;
35467 }
35468 else
35469 return;
35470 }
35471 else
35472 {
35473
35474
35475
35476
35477 f->last_tab_bar_item = -1;
35478 }
35479 #endif
35480
35481 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35482
35483
35484 if (EQ (window, f->tool_bar_window))
35485 {
35486 note_tool_bar_highlight (f, x, y);
35487 return;
35488 }
35489 #endif
35490
35491
35492 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35493 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35494 {
35495 note_mode_line_or_margin_highlight (window, x, y, part);
35496
35497 #ifdef HAVE_WINDOW_SYSTEM
35498 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35499 {
35500 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35501
35502 goto set_cursor;
35503 }
35504 else
35505 #endif
35506 return;
35507 }
35508
35509 #ifdef HAVE_WINDOW_SYSTEM
35510 if (part == ON_VERTICAL_BORDER)
35511 {
35512 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35513 help_echo_string = build_string ("drag-mouse-1: resize");
35514 goto set_cursor;
35515 }
35516 else if (part == ON_RIGHT_DIVIDER)
35517 {
35518 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35519 help_echo_string = build_string ("drag-mouse-1: resize");
35520 goto set_cursor;
35521 }
35522 else if (part == ON_BOTTOM_DIVIDER)
35523 if (! WINDOW_BOTTOMMOST_P (w)
35524 || minibuf_level
35525 || NILP (Vresize_mini_windows))
35526 {
35527 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35528 help_echo_string = build_string ("drag-mouse-1: resize");
35529 goto set_cursor;
35530 }
35531 else
35532 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35533 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35534 || part == ON_VERTICAL_SCROLL_BAR
35535 || part == ON_HORIZONTAL_SCROLL_BAR)
35536 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35537 else
35538 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35539 #endif
35540
35541
35542
35543 b = XBUFFER (w->contents);
35544 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35545 {
35546 int hpos, vpos, dx, dy, area = LAST_AREA;
35547 ptrdiff_t pos;
35548 struct glyph *glyph;
35549 Lisp_Object object;
35550 Lisp_Object mouse_face = Qnil, position;
35551 Lisp_Object *overlay_vec = NULL;
35552 ptrdiff_t i, noverlays;
35553 struct buffer *obuf;
35554 ptrdiff_t obegv, ozv;
35555 bool same_region;
35556
35557
35558 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35559
35560 #ifdef HAVE_WINDOW_SYSTEM
35561
35562 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35563 {
35564 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35565 if (img != NULL && IMAGEP (img->spec))
35566 {
35567 Lisp_Object image_map, hotspot;
35568 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35569 !NILP (image_map))
35570 && (hotspot = find_hot_spot (image_map,
35571 glyph->slice.img.x + dx,
35572 glyph->slice.img.y + dy),
35573 CONSP (hotspot))
35574 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35575 {
35576 Lisp_Object plist;
35577
35578
35579
35580
35581
35582 hotspot = XCDR (hotspot);
35583 if (CONSP (hotspot)
35584 && (plist = XCAR (hotspot), CONSP (plist)))
35585 {
35586 pointer = plist_get (plist, Qpointer);
35587 if (NILP (pointer))
35588 pointer = Qhand;
35589 help_echo_string = plist_get (plist, Qhelp_echo);
35590 if (!NILP (help_echo_string))
35591 {
35592 help_echo_window = window;
35593 help_echo_object = glyph->object;
35594 help_echo_pos = glyph->charpos;
35595 }
35596 }
35597 }
35598 if (NILP (pointer))
35599 pointer = plist_get (XCDR (img->spec), QCpointer);
35600 }
35601 }
35602 #endif
35603
35604
35605 if (glyph == NULL
35606 || area != TEXT_AREA
35607 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35608
35609
35610
35611
35612
35613 || NILP (glyph->object)
35614
35615
35616
35617
35618 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35619 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35620 && glyph->type == STRETCH_GLYPH
35621 && glyph->avoid_cursor_p))
35622 {
35623 if (clear_mouse_face (hlinfo))
35624 cursor = No_Cursor;
35625 if (FRAME_WINDOW_P (f) && NILP (pointer))
35626 {
35627 #ifdef HAVE_WINDOW_SYSTEM
35628 if (area != TEXT_AREA)
35629 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35630 else
35631 pointer = Vvoid_text_area_pointer;
35632 #endif
35633 }
35634 goto set_cursor;
35635 }
35636
35637 pos = glyph->charpos;
35638 object = glyph->object;
35639 if (!STRINGP (object) && !BUFFERP (object))
35640 goto set_cursor;
35641
35642
35643 if (BUFFERP (object) && pos > BUF_Z (b))
35644 goto set_cursor;
35645
35646
35647
35648 obuf = current_buffer;
35649 current_buffer = b;
35650 obegv = BEGV;
35651 ozv = ZV;
35652 BEGV = BEG;
35653 ZV = Z;
35654
35655
35656 position = make_fixnum (pos);
35657
35658 USE_SAFE_ALLOCA;
35659
35660 if (BUFFERP (object))
35661 {
35662
35663 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35664
35665 noverlays = sort_overlays (overlay_vec, noverlays, w);
35666 }
35667 else
35668 noverlays = 0;
35669
35670 if (NILP (Vmouse_highlight))
35671 {
35672 clear_mouse_face (hlinfo);
35673 goto check_help_echo;
35674 }
35675
35676 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35677
35678 if (same_region)
35679 cursor = No_Cursor;
35680
35681
35682 if (! same_region
35683
35684
35685
35686
35687
35688 || (!hlinfo->mouse_face_hidden
35689 && OVERLAYP (hlinfo->mouse_face_overlay)
35690
35691 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35692 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35693 {
35694
35695 Lisp_Object overlay = Qnil;
35696 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35697 {
35698 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35699 if (!NILP (mouse_face))
35700 overlay = overlay_vec[i];
35701 }
35702
35703
35704
35705 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35706 goto check_help_echo;
35707
35708
35709 if (clear_mouse_face (hlinfo))
35710 cursor = No_Cursor;
35711
35712
35713 hlinfo->mouse_face_overlay = overlay;
35714
35715
35716 if (NILP (overlay))
35717 mouse_face = Fget_text_property (position, Qmouse_face, object);
35718
35719
35720
35721 if (!NILP (mouse_face) && STRINGP (object))
35722 {
35723
35724
35725 Lisp_Object s, e;
35726 ptrdiff_t ignore;
35727
35728 s = Fprevious_single_property_change
35729 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35730 e = Fnext_single_property_change
35731 (position, Qmouse_face, object, Qnil);
35732 if (NILP (s))
35733 s = make_fixnum (0);
35734 if (NILP (e))
35735 e = make_fixnum (SCHARS (object));
35736 mouse_face_from_string_pos (w, hlinfo, object,
35737 XFIXNUM (s), XFIXNUM (e));
35738 hlinfo->mouse_face_past_end = false;
35739 hlinfo->mouse_face_window = window;
35740 hlinfo->mouse_face_face_id
35741 = face_at_string_position (w, object, pos, 0, &ignore,
35742 glyph->face_id, true, 0);
35743 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35744 cursor = No_Cursor;
35745 }
35746 else
35747 {
35748
35749
35750 Lisp_Object buffer UNINIT;
35751 Lisp_Object disp_string UNINIT;
35752
35753 if (STRINGP (object))
35754 {
35755
35756
35757 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35758 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35759 pos = string_buffer_position (object, start);
35760 if (pos > 0)
35761 {
35762 mouse_face = get_char_property_and_overlay
35763 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35764 buffer = w->contents;
35765 disp_string = object;
35766 }
35767 }
35768 else
35769 {
35770 buffer = object;
35771 disp_string = Qnil;
35772 }
35773
35774 if (!NILP (mouse_face))
35775 {
35776 Lisp_Object before, after;
35777 Lisp_Object before_string, after_string;
35778
35779
35780
35781
35782
35783
35784
35785
35786
35787
35788 Lisp_Object lim1
35789 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35790 ? Fmarker_position (w->start)
35791 : Qnil;
35792 Lisp_Object lim2
35793 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35794 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35795 - w->window_end_pos)
35796 : Qnil;
35797
35798 if (NILP (overlay))
35799 {
35800
35801 before = Fprevious_single_property_change
35802 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35803 after = Fnext_single_property_change
35804 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35805 before_string = after_string = Qnil;
35806 }
35807 else
35808 {
35809
35810 before = Foverlay_start (overlay);
35811 after = Foverlay_end (overlay);
35812 before_string = Foverlay_get (overlay, Qbefore_string);
35813 after_string = Foverlay_get (overlay, Qafter_string);
35814
35815 if (!STRINGP (before_string)) before_string = Qnil;
35816 if (!STRINGP (after_string)) after_string = Qnil;
35817 }
35818
35819 mouse_face_from_buffer_pos (window, hlinfo, pos,
35820 NILP (before)
35821 ? 1
35822 : XFIXNAT (before),
35823 NILP (after)
35824 ? BUF_Z (XBUFFER (buffer))
35825 : XFIXNAT (after),
35826 before_string, after_string,
35827 disp_string);
35828 cursor = No_Cursor;
35829 }
35830 }
35831 }
35832
35833 check_help_echo:
35834
35835
35836 if (NILP (help_echo_string)) {
35837 Lisp_Object help, overlay;
35838
35839
35840 help = overlay = Qnil;
35841 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35842 {
35843 overlay = overlay_vec[i];
35844 help = Foverlay_get (overlay, Qhelp_echo);
35845 }
35846
35847 if (!NILP (help))
35848 {
35849 help_echo_string = help;
35850 help_echo_window = window;
35851 help_echo_object = overlay;
35852 help_echo_pos = pos;
35853 }
35854 else
35855 {
35856 Lisp_Object obj = glyph->object;
35857 ptrdiff_t charpos = glyph->charpos;
35858
35859
35860 if (STRINGP (obj)
35861 && charpos >= 0
35862 && charpos < SCHARS (obj))
35863 {
35864 help = Fget_text_property (make_fixnum (charpos),
35865 Qhelp_echo, obj);
35866 if (NILP (help))
35867 {
35868
35869
35870 struct glyph_row *r
35871 = MATRIX_ROW (w->current_matrix, vpos);
35872 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35873 ptrdiff_t p = string_buffer_position (obj, start);
35874 if (p > 0)
35875 {
35876 help = Fget_char_property (make_fixnum (p),
35877 Qhelp_echo, w->contents);
35878 if (!NILP (help))
35879 {
35880 charpos = p;
35881 obj = w->contents;
35882 }
35883 }
35884 }
35885 }
35886 else if (BUFFERP (obj)
35887 && charpos >= BEGV
35888 && charpos < ZV)
35889 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35890 obj);
35891
35892 if (!NILP (help))
35893 {
35894 help_echo_string = help;
35895 help_echo_window = window;
35896 help_echo_object = obj;
35897 help_echo_pos = charpos;
35898 }
35899 }
35900 }
35901
35902 #ifdef HAVE_WINDOW_SYSTEM
35903
35904 if (FRAME_WINDOW_P (f) && NILP (pointer))
35905 {
35906
35907 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35908 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35909
35910 if (NILP (pointer))
35911 {
35912 Lisp_Object obj = glyph->object;
35913 ptrdiff_t charpos = glyph->charpos;
35914
35915
35916 if (STRINGP (obj)
35917 && charpos >= 0
35918 && charpos < SCHARS (obj))
35919 {
35920 pointer = Fget_text_property (make_fixnum (charpos),
35921 Qpointer, obj);
35922 if (NILP (pointer))
35923 {
35924
35925
35926 struct glyph_row *r
35927 = MATRIX_ROW (w->current_matrix, vpos);
35928 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35929 ptrdiff_t p = string_buffer_position (obj, start);
35930 if (p > 0)
35931 pointer = Fget_char_property (make_fixnum (p),
35932 Qpointer, w->contents);
35933 }
35934 }
35935 else if (BUFFERP (obj)
35936 && charpos >= BEGV
35937 && charpos < ZV)
35938 pointer = Fget_text_property (make_fixnum (charpos),
35939 Qpointer, obj);
35940 }
35941 }
35942 #endif
35943
35944 BEGV = obegv;
35945 ZV = ozv;
35946 current_buffer = obuf;
35947 SAFE_FREE ();
35948 }
35949
35950 set_cursor:
35951 define_frame_cursor1 (f, cursor, pointer);
35952 }
35953
35954
35955
35956
35957
35958
35959
35960 void
35961 gui_clear_window_mouse_face (struct window *w)
35962 {
35963 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
35964 Lisp_Object window;
35965
35966 block_input ();
35967 XSETWINDOW (window, w);
35968 if (EQ (window, hlinfo->mouse_face_window))
35969 clear_mouse_face (hlinfo);
35970 unblock_input ();
35971 }
35972
35973
35974
35975
35976
35977
35978 void
35979 cancel_mouse_face (struct frame *f)
35980 {
35981 Lisp_Object window;
35982 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35983
35984 window = hlinfo->mouse_face_window;
35985 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
35986 reset_mouse_highlight (hlinfo);
35987 }
35988
35989
35990
35991
35992
35993
35994
35995 #ifdef HAVE_WINDOW_SYSTEM
35996
35997
35998
35999
36000 static void
36001 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
36002 enum glyph_row_area area)
36003 {
36004 struct glyph *first = row->glyphs[area];
36005 struct glyph *end = row->glyphs[area] + row->used[area];
36006 struct glyph *last;
36007 int first_x, start_x, x;
36008
36009 if (area == TEXT_AREA && row->fill_line_p)
36010
36011 draw_glyphs (w, row->x, row, area,
36012 0, row->used[area],
36013 DRAW_NORMAL_TEXT, 0);
36014 else
36015 {
36016
36017
36018
36019 start_x = window_box_left_offset (w, area);
36020 x = start_x;
36021 if (area == TEXT_AREA)
36022 x += row->x;
36023
36024
36025 while (first < end
36026 && x + first->pixel_width < r->x)
36027 {
36028 x += first->pixel_width;
36029 ++first;
36030 }
36031
36032
36033 last = first;
36034 first_x = x;
36035
36036
36037
36038 int r_end = r->x + r->width;
36039 while (last < end && x < r_end)
36040 {
36041 x += last->pixel_width;
36042 ++last;
36043 }
36044
36045
36046 if (last > first)
36047 draw_glyphs (w, first_x - start_x, row, area,
36048 first - row->glyphs[area], last - row->glyphs[area],
36049 DRAW_NORMAL_TEXT, 0);
36050 }
36051 }
36052
36053
36054
36055
36056
36057
36058 static bool
36059 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
36060 {
36061 eassert (row->enabled_p);
36062
36063 if (row->mode_line_p || w->pseudo_window_p)
36064 draw_glyphs (w, 0, row, TEXT_AREA,
36065 0, row->used[TEXT_AREA],
36066 DRAW_NORMAL_TEXT, 0);
36067 else
36068 {
36069 if (row->used[LEFT_MARGIN_AREA])
36070 expose_area (w, row, r, LEFT_MARGIN_AREA);
36071 if (row->used[TEXT_AREA])
36072 expose_area (w, row, r, TEXT_AREA);
36073 if (row->used[RIGHT_MARGIN_AREA])
36074 expose_area (w, row, r, RIGHT_MARGIN_AREA);
36075 draw_row_fringe_bitmaps (w, row);
36076 }
36077
36078 return row->mouse_face_p;
36079 }
36080
36081
36082
36083
36084
36085
36086
36087
36088
36089
36090 static void
36091 expose_overlaps (struct window *w,
36092 struct glyph_row *first_overlapping_row,
36093 struct glyph_row *last_overlapping_row,
36094 const Emacs_Rectangle *r)
36095 {
36096 struct glyph_row *row;
36097
36098 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
36099 if (row->overlapping_p)
36100 {
36101 eassert (row->enabled_p && !row->mode_line_p);
36102
36103 row->clip = r;
36104 if (row->used[LEFT_MARGIN_AREA])
36105 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
36106
36107 if (row->used[TEXT_AREA])
36108 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
36109
36110 if (row->used[RIGHT_MARGIN_AREA])
36111 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
36112 row->clip = NULL;
36113 }
36114 }
36115
36116
36117
36118
36119 static bool
36120 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
36121 {
36122 Emacs_Rectangle cr, result;
36123 struct glyph *cursor_glyph;
36124 struct glyph_row *row;
36125
36126 if (w->phys_cursor.vpos >= 0
36127 && w->phys_cursor.vpos < w->current_matrix->nrows
36128 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
36129 row->enabled_p)
36130 && row->cursor_in_fringe_p)
36131 {
36132
36133 cr.x = window_box_right_offset (w,
36134 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
36135 ? RIGHT_MARGIN_AREA
36136 : TEXT_AREA));
36137 cr.y = row->y;
36138 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
36139 cr.height = row->height;
36140 return gui_intersect_rectangles (&cr, r, &result);
36141 }
36142
36143 cursor_glyph = get_phys_cursor_glyph (w);
36144 if (cursor_glyph)
36145 {
36146
36147
36148 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
36149 cr.y = w->phys_cursor.y;
36150 cr.width = cursor_glyph->pixel_width;
36151 cr.height = w->phys_cursor_height;
36152
36153
36154 return gui_intersect_rectangles (&cr, r, &result);
36155 }
36156
36157 return false;
36158 }
36159
36160
36161
36162
36163
36164
36165 void
36166 gui_draw_vertical_border (struct window *w)
36167 {
36168 struct frame *f = XFRAME (WINDOW_FRAME (w));
36169
36170
36171
36172
36173
36174
36175
36176
36177
36178 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
36179 return;
36180
36181
36182
36183
36184 if (!WINDOW_RIGHTMOST_P (w)
36185 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
36186 {
36187 int x0, x1, y0, y1;
36188
36189 window_box_edges (w, &x0, &y0, &x1, &y1);
36190 y1 -= 1;
36191
36192 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36193 x1 -= 1;
36194
36195 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
36196 }
36197
36198 if (!WINDOW_LEFTMOST_P (w)
36199 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
36200 {
36201 int x0, x1, y0, y1;
36202
36203 window_box_edges (w, &x0, &y0, &x1, &y1);
36204 y1 -= 1;
36205
36206 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36207 x0 -= 1;
36208
36209 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
36210 }
36211 }
36212
36213
36214
36215
36216 void
36217 gui_draw_right_divider (struct window *w)
36218 {
36219 struct frame *f = WINDOW_XFRAME (w);
36220
36221 if (w->mini || w->pseudo_window_p)
36222 return;
36223 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36224 {
36225 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
36226 int x1 = WINDOW_RIGHT_EDGE_X (w);
36227 int y0 = WINDOW_TOP_EDGE_Y (w);
36228 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36229
36230
36231
36232 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
36233 && !NILP (w->parent)
36234 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
36235 && !NILP (w->next))
36236 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36237
36238 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36239 }
36240 }
36241
36242 static void
36243 gui_draw_bottom_divider (struct window *w)
36244 {
36245 struct frame *f = XFRAME (WINDOW_FRAME (w));
36246
36247 if (w->mini || w->pseudo_window_p)
36248 return;
36249 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36250 {
36251 int x0 = WINDOW_LEFT_EDGE_X (w);
36252 int x1 = WINDOW_RIGHT_EDGE_X (w);
36253 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36254 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36255 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
36256
36257
36258
36259 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
36260 && p
36261 && ((WINDOW_VERTICAL_COMBINATION_P (p)
36262 && !NILP (w->next))
36263 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
36264 && NILP (w->next)
36265 && !NILP (p->parent)
36266 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
36267 && !NILP (XWINDOW (p->parent)->next))))
36268 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
36269
36270 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36271 }
36272 }
36273
36274
36275
36276
36277
36278
36279 static bool
36280 expose_window (struct window *w, const Emacs_Rectangle *fr)
36281 {
36282 struct frame *f = XFRAME (w->frame);
36283 Emacs_Rectangle wr, r;
36284 bool mouse_face_overwritten_p = false;
36285
36286
36287
36288
36289
36290 if (w->current_matrix == NULL)
36291 return false;
36292
36293
36294
36295
36296 if (w->must_be_updated_p)
36297 {
36298 SET_FRAME_GARBAGED (f);
36299 return false;
36300 }
36301
36302
36303 wr.x = WINDOW_LEFT_EDGE_X (w);
36304 wr.y = WINDOW_TOP_EDGE_Y (w);
36305 wr.width = WINDOW_PIXEL_WIDTH (w);
36306 wr.height = WINDOW_PIXEL_HEIGHT (w);
36307
36308 if (gui_intersect_rectangles (fr, &wr, &r))
36309 {
36310 int yb = window_text_bottom_y (w);
36311 struct glyph_row *row;
36312 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36313
36314 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36315 r.x, r.y, r.width, r.height);
36316
36317
36318 r.x -= WINDOW_LEFT_EDGE_X (w);
36319 r.y -= WINDOW_TOP_EDGE_Y (w);
36320
36321
36322 bool cursor_cleared_p = (!w->pseudo_window_p
36323 && phys_cursor_in_rect_p (w, &r));
36324 if (cursor_cleared_p)
36325 gui_clear_cursor (w);
36326
36327
36328
36329
36330
36331
36332 bool phys_cursor_on_p = w->phys_cursor_on_p;
36333
36334
36335
36336
36337 int r_bottom = r.y + r.height;
36338
36339
36340
36341
36342
36343 bool buffer_changed = false;
36344 struct buffer *oldbuf = current_buffer;
36345 if (!w->pseudo_window_p)
36346 {
36347 set_buffer_internal_1 (XBUFFER (w->contents));
36348 buffer_changed = true;
36349 }
36350
36351
36352 first_overlapping_row = last_overlapping_row = NULL;
36353 for (row = w->current_matrix->rows;
36354 row->enabled_p;
36355 ++row)
36356 {
36357 int y0 = row->y;
36358 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36359
36360 if ((y0 >= r.y && y0 < r_bottom)
36361 || (y1 > r.y && y1 < r_bottom)
36362 || (r.y >= y0 && r.y < y1)
36363 || (r_bottom > y0 && r_bottom < y1))
36364 {
36365
36366
36367 if (row->overlapping_p && !row->mode_line_p)
36368 {
36369 if (first_overlapping_row == NULL)
36370 first_overlapping_row = row;
36371 last_overlapping_row = row;
36372 }
36373
36374 row->clip = fr;
36375 if (expose_line (w, row, &r))
36376 mouse_face_overwritten_p = true;
36377 row->clip = NULL;
36378 }
36379 else if (row->overlapping_p)
36380 {
36381
36382 if (y0 < r.y
36383 ? y0 + row->phys_height > r.y
36384 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36385 {
36386 if (first_overlapping_row == NULL)
36387 first_overlapping_row = row;
36388 last_overlapping_row = row;
36389 }
36390 }
36391
36392 if (y1 >= yb)
36393 break;
36394 }
36395
36396 if (buffer_changed)
36397 set_buffer_internal_1 (oldbuf);
36398
36399
36400 if (window_wants_mode_line (w)
36401 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36402 row->enabled_p)
36403 && row->y < r_bottom)
36404 {
36405 if (expose_line (w, row, &r))
36406 mouse_face_overwritten_p = true;
36407 }
36408
36409 if (!w->pseudo_window_p)
36410 {
36411
36412 if (first_overlapping_row)
36413 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36414 fr);
36415
36416
36417 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36418 gui_draw_right_divider (w);
36419 else
36420 gui_draw_vertical_border (w);
36421
36422 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36423 gui_draw_bottom_divider (w);
36424
36425
36426 if (cursor_cleared_p
36427 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36428 update_window_cursor (w, true);
36429 }
36430 }
36431
36432 return mouse_face_overwritten_p;
36433 }
36434
36435
36436
36437
36438
36439
36440
36441 static bool
36442 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36443 {
36444 struct frame *f = XFRAME (w->frame);
36445 bool mouse_face_overwritten_p = false;
36446
36447 while (w && !FRAME_GARBAGED_P (f))
36448 {
36449 mouse_face_overwritten_p
36450 |= (WINDOWP (w->contents)
36451 ? expose_window_tree (XWINDOW (w->contents), r)
36452 : expose_window (w, r));
36453
36454 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36455 }
36456
36457 return mouse_face_overwritten_p;
36458 }
36459
36460
36461
36462
36463
36464
36465
36466
36467 void
36468 expose_frame (struct frame *f, int x, int y, int w, int h)
36469 {
36470 Emacs_Rectangle r;
36471 bool mouse_face_overwritten_p = false;
36472
36473 if (FRAME_GARBAGED_P (f))
36474 {
36475 redisplay_trace ("expose_frame garbaged\n");
36476 return;
36477 }
36478
36479
36480
36481
36482 if (FRAME_FACE_CACHE (f) == NULL
36483 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36484 {
36485 redisplay_trace ("expose_frame no faces\n");
36486 return;
36487 }
36488
36489 if (w == 0 || h == 0)
36490 {
36491 r.x = r.y = 0;
36492 r.width = FRAME_TEXT_WIDTH (f);
36493 r.height = FRAME_TEXT_HEIGHT (f);
36494 }
36495 else
36496 {
36497 r.x = x;
36498 r.y = y;
36499 r.width = w;
36500 r.height = h;
36501 }
36502
36503 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36504 r.x, r.y, r.width, r.height);
36505 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36506
36507 if (WINDOWP (f->tab_bar_window))
36508 mouse_face_overwritten_p
36509 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36510
36511 #ifndef HAVE_EXT_TOOL_BAR
36512 if (WINDOWP (f->tool_bar_window))
36513 mouse_face_overwritten_p
36514 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36515 #endif
36516
36517 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
36518 if (WINDOWP (f->menu_bar_window))
36519 mouse_face_overwritten_p
36520 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36521 #endif
36522
36523
36524
36525
36526
36527
36528
36529
36530
36531
36532
36533
36534
36535
36536 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36537 {
36538 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36539 if (f == hlinfo->mouse_face_mouse_frame)
36540 {
36541 int mouse_x = hlinfo->mouse_face_mouse_x;
36542 int mouse_y = hlinfo->mouse_face_mouse_y;
36543 clear_mouse_face (hlinfo);
36544 note_mouse_highlight (f, mouse_x, mouse_y);
36545 }
36546 }
36547 }
36548
36549
36550
36551
36552
36553
36554
36555 bool
36556 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36557 Emacs_Rectangle *result)
36558 {
36559 const Emacs_Rectangle *left, *right;
36560 const Emacs_Rectangle *upper, *lower;
36561 bool intersection_p = false;
36562
36563
36564 if (r1->x < r2->x)
36565 left = r1, right = r2;
36566 else
36567 left = r2, right = r1;
36568
36569
36570
36571 if (right->x <= left->x + left->width)
36572 {
36573 result->x = right->x;
36574
36575
36576
36577 result->width = (min (left->x + left->width, right->x + right->width)
36578 - result->x);
36579
36580
36581 if (r1->y < r2->y)
36582 upper = r1, lower = r2;
36583 else
36584 upper = r2, lower = r1;
36585
36586
36587
36588 if (lower->y <= upper->y + upper->height)
36589 {
36590 result->y = lower->y;
36591
36592
36593
36594 result->height = (min (lower->y + lower->height,
36595 upper->y + upper->height)
36596 - result->y);
36597 intersection_p = true;
36598 }
36599 }
36600
36601 return intersection_p;
36602 }
36603
36604
36605
36606
36607
36608
36609 void
36610 gui_union_rectangles (const Emacs_Rectangle *a, const Emacs_Rectangle *b,
36611 Emacs_Rectangle *result)
36612 {
36613 struct gui_box a_box, b_box, result_box;
36614
36615
36616
36617 if (!a->width || !a->height)
36618 {
36619 *result = *b;
36620 return;
36621 }
36622 else if (!b->width || !b->height)
36623 {
36624 *result = *a;
36625 return;
36626 }
36627
36628
36629 a_box.x1 = a->x;
36630 a_box.y1 = a->y;
36631 a_box.x2 = a->x + a->width;
36632 a_box.y2 = a->y + a->height;
36633
36634 b_box.x1 = b->x;
36635 b_box.y1 = b->y;
36636 b_box.x2 = b->x + b->width;
36637 b_box.y2 = b->y + b->height;
36638
36639
36640 result_box.x1 = min (a_box.x1, b_box.x1);
36641 result_box.y1 = min (a_box.y1, b_box.y1);
36642 result_box.x2 = max (a_box.x2, b_box.x2);
36643 result_box.y2 = max (a_box.y2, b_box.y2);
36644
36645
36646
36647 result->x = result_box.x1;
36648 result->y = result_box.y1;
36649 result->width = result_box.x2 - result_box.x1;
36650 result->height = result_box.y2 - result_box.y1;
36651 }
36652
36653 #endif
36654
36655
36656
36657
36658
36659
36660 void
36661 syms_of_xdisp (void)
36662 {
36663 Vwith_echo_area_save_vector = Qnil;
36664 staticpro (&Vwith_echo_area_save_vector);
36665
36666 Vmessage_stack = Qnil;
36667 staticpro (&Vmessage_stack);
36668
36669
36670 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36671
36672 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36673
36674 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36675 scroll_minibuffer_conservatively,
36676 doc:
36677
36678 );
36679 scroll_minibuffer_conservatively = true;
36680
36681 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36682 doc:
36683
36684
36685
36686
36687
36688 );
36689 inhibit_message = false;
36690
36691 message_dolog_marker1 = Fmake_marker ();
36692 staticpro (&message_dolog_marker1);
36693 message_dolog_marker2 = Fmake_marker ();
36694 staticpro (&message_dolog_marker2);
36695 message_dolog_marker3 = Fmake_marker ();
36696 staticpro (&message_dolog_marker3);
36697
36698 defsubr (&Sset_buffer_redisplay);
36699 #ifdef GLYPH_DEBUG
36700 defsubr (&Sdump_frame_glyph_matrix);
36701 defsubr (&Sdump_glyph_matrix);
36702 defsubr (&Sdump_glyph_row);
36703 defsubr (&Sdump_tab_bar_row);
36704 defsubr (&Sdump_tool_bar_row);
36705 defsubr (&Strace_redisplay);
36706 defsubr (&Strace_to_stderr);
36707 #endif
36708 #ifdef HAVE_WINDOW_SYSTEM
36709 defsubr (&Stab_bar_height);
36710 defsubr (&Stool_bar_height);
36711 defsubr (&Slookup_image_map);
36712 #endif
36713 defsubr (&Sline_pixel_height);
36714 defsubr (&Sformat_mode_line);
36715 defsubr (&Sinvisible_p);
36716 defsubr (&Scurrent_bidi_paragraph_direction);
36717 defsubr (&Swindow_text_pixel_size);
36718 defsubr (&Sbuffer_text_pixel_size);
36719 defsubr (&Smove_point_visually);
36720 defsubr (&Sbidi_find_overridden_directionality);
36721 defsubr (&Sdisplay__line_is_continued_p);
36722 defsubr (&Sget_display_property);
36723 defsubr (&Slong_line_optimizations_p);
36724
36725 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36726 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36727 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36728 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36729 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36730 DEFSYM (Qeval, "eval");
36731 DEFSYM (QCdata, ":data");
36732
36733
36734 DEFSYM (Qdisplay, "display");
36735 DEFSYM (Qspace_width, "space-width");
36736 DEFSYM (Qraise, "raise");
36737 DEFSYM (Qslice, "slice");
36738 DEFSYM (Qspace, "space");
36739 DEFSYM (Qmargin, "margin");
36740 DEFSYM (Qpointer, "pointer");
36741 DEFSYM (Qleft_margin, "left-margin");
36742 DEFSYM (Qright_margin, "right-margin");
36743 DEFSYM (Qcenter, "center");
36744 DEFSYM (Qline_height, "line-height");
36745 DEFSYM (QCalign_to, ":align-to");
36746 DEFSYM (QCrelative_width, ":relative-width");
36747 DEFSYM (QCrelative_height, ":relative-height");
36748 DEFSYM (QCeval, ":eval");
36749 DEFSYM (QCpropertize, ":propertize");
36750 DEFSYM (QCfile, ":file");
36751 DEFSYM (Qfontified, "fontified");
36752 DEFSYM (Qfontification_functions, "fontification-functions");
36753 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36754 "long-line-optimizations-in-fontification-functions");
36755
36756
36757
36758 DEFSYM (Qdisable_eval, "disable-eval");
36759
36760
36761 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36762
36763
36764 DEFSYM (Qline_number, "line-number");
36765 DEFSYM (Qline_number_current_line, "line-number-current-line");
36766 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36767 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36768
36769 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36770
36771
36772 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36773
36774
36775 DEFSYM (Qescape_glyph, "escape-glyph");
36776
36777
36778
36779 DEFSYM (Qnobreak_space, "nobreak-space");
36780 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36781
36782
36783
36784 DEFSYM (Qimage, "image");
36785
36786
36787 DEFSYM (Qtext, "text");
36788 DEFSYM (Qboth, "both");
36789 DEFSYM (Qboth_horiz, "both-horiz");
36790 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36791
36792
36793 DEFSYM (QCmap, ":map");
36794 DEFSYM (QCpointer, ":pointer");
36795 DEFSYM (Qrect, "rect");
36796 DEFSYM (Qcircle, "circle");
36797 DEFSYM (Qpoly, "poly");
36798
36799 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36800
36801 DEFSYM (Qgrow_only, "grow-only");
36802 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36803 DEFSYM (Qposition, "position");
36804 DEFSYM (Qbuffer_position, "buffer-position");
36805 DEFSYM (Qobject, "object");
36806
36807
36808 DEFSYM (Qbar, "bar");
36809 DEFSYM (Qhbar, "hbar");
36810 DEFSYM (Qbox, "box");
36811 DEFSYM (Qhollow, "hollow");
36812
36813
36814 DEFSYM (Qhand, "hand");
36815 DEFSYM (Qarrow, "arrow");
36816
36817
36818 DEFSYM (Qdragging, "dragging");
36819 DEFSYM (Qdropping, "dropping");
36820 DEFSYM (Qdrag_source, "drag-source");
36821
36822 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36823 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36824 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36825
36826 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36827
36828 list_of_error = list1 (Qerror);
36829 staticpro (&list_of_error);
36830
36831
36832
36833
36834
36835 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36836 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36837
36838
36839
36840 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36841 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36842
36843 echo_buffer[0] = echo_buffer[1] = Qnil;
36844 staticpro (&echo_buffer[0]);
36845 staticpro (&echo_buffer[1]);
36846
36847 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36848 staticpro (&echo_area_buffer[0]);
36849 staticpro (&echo_area_buffer[1]);
36850
36851 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36852 doc:
36853
36854
36855
36856 );
36857 Vmessages_buffer_name = build_string ("*Messages*");
36858
36859 mode_line_proptrans_alist = Qnil;
36860 staticpro (&mode_line_proptrans_alist);
36861 mode_line_string_list = Qnil;
36862 staticpro (&mode_line_string_list);
36863 mode_line_string_face = Qnil;
36864 staticpro (&mode_line_string_face);
36865 mode_line_string_face_prop = Qnil;
36866 staticpro (&mode_line_string_face_prop);
36867 Vmode_line_unwind_vector = Qnil;
36868 staticpro (&Vmode_line_unwind_vector);
36869
36870 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36871
36872 help_echo_string = Qnil;
36873 staticpro (&help_echo_string);
36874 help_echo_object = Qnil;
36875 staticpro (&help_echo_object);
36876 help_echo_window = Qnil;
36877 staticpro (&help_echo_window);
36878 previous_help_echo_string = Qnil;
36879 staticpro (&previous_help_echo_string);
36880 help_echo_pos = -1;
36881
36882 DEFSYM (Qright_to_left, "right-to-left");
36883 DEFSYM (Qleft_to_right, "left-to-right");
36884 defsubr (&Sbidi_resolved_levels);
36885
36886 #ifdef HAVE_WINDOW_SYSTEM
36887 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36888 doc:
36889
36890 );
36891 x_stretch_cursor_p = 0;
36892 #endif
36893
36894 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36895 doc:
36896 );
36897 Vshow_trailing_whitespace = Qnil;
36898
36899 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36900 doc:
36901
36902
36903 );
36904 Vmode_line_compact = Qnil;
36905 DEFSYM (Qlong, "long");
36906
36907 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36908 doc:
36909
36910
36911
36912
36913
36914
36915
36916
36917
36918
36919
36920 );
36921 Vnobreak_char_display = Qt;
36922
36923 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
36924 doc:
36925
36926
36927
36928
36929
36930
36931
36932
36933
36934
36935
36936
36937
36938
36939
36940 );
36941 nobreak_char_ascii_display = false;
36942
36943 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
36944 doc:
36945
36946
36947 );
36948 Vvoid_text_area_pointer = Qarrow;
36949
36950 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
36951 doc:
36952 );
36953 Vinhibit_redisplay = Qnil;
36954
36955 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
36956 doc: );
36957 Vglobal_mode_string = Qnil;
36958
36959 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
36960 doc:
36961
36962 );
36963 Voverlay_arrow_position = Qnil;
36964
36965 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
36966 doc:
36967 );
36968 Voverlay_arrow_string = build_pure_c_string ("=>");
36969
36970 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
36971 doc:
36972
36973 );
36974 Voverlay_arrow_variable_list
36975 = list1 (intern_c_string ("overlay-arrow-position"));
36976
36977 DEFVAR_INT ("scroll-step", emacs_scroll_step,
36978 doc:
36979
36980
36981
36982 );
36983
36984 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
36985 doc:
36986
36987
36988
36989
36990
36991
36992
36993
36994
36995 );
36996 scroll_conservatively = 0;
36997
36998 DEFVAR_INT ("scroll-margin", scroll_margin,
36999 doc:
37000
37001 );
37002 scroll_margin = 0;
37003
37004 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
37005 doc:
37006
37007
37008
37009 );
37010 Vmaximum_scroll_margin = make_float (0.25);
37011
37012 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
37013 doc:
37014 );
37015 Vdisplay_pixels_per_inch = make_float (72.0);
37016
37017 #ifdef GLYPH_DEBUG
37018 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
37019 #endif
37020
37021 DEFVAR_LISP ("truncate-partial-width-windows",
37022 Vtruncate_partial_width_windows,
37023 doc:
37024
37025
37026
37027
37028
37029
37030
37031
37032
37033
37034
37035
37036
37037
37038
37039 );
37040 Vtruncate_partial_width_windows = make_fixnum (50);
37041
37042 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
37043
37044
37045
37046
37047
37048
37049
37050
37051
37052
37053
37054
37055
37056 );
37057 word_wrap_by_category = false;
37058
37059 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
37060 doc:
37061
37062 );
37063 Vline_number_display_limit = Qnil;
37064
37065 DEFVAR_INT ("line-number-display-limit-width",
37066 line_number_display_limit_width,
37067 doc:
37068
37069 );
37070 line_number_display_limit_width = 200;
37071
37072 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
37073 doc:
37074
37075 );
37076 highlight_nonselected_windows = false;
37077
37078 DEFVAR_BOOL ("multiple-frames", multiple_frames,
37079 doc:
37080
37081
37082 );
37083
37084 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
37085 doc:
37086
37087
37088
37089
37090 );
37091
37092 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
37093 doc:
37094
37095
37096
37097
37098
37099 );
37100
37101
37102 Lisp_Object icon_title_name_format
37103 = pure_list (empty_unibyte_string,
37104 build_pure_c_string ("%b - GNU Emacs at "),
37105 intern_c_string ("system-name"));
37106 Vicon_title_format
37107 = Vframe_title_format
37108 = pure_list (intern_c_string ("multiple-frames"),
37109 build_pure_c_string ("%b"),
37110 icon_title_name_format);
37111
37112 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
37113 doc:
37114
37115 );
37116 Vmessage_log_max = make_fixnum (1000);
37117
37118 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
37119 doc:
37120
37121
37122
37123
37124
37125
37126
37127
37128
37129
37130
37131
37132
37133 );
37134 Vwindow_scroll_functions = Qnil;
37135
37136 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
37137 doc:
37138
37139
37140
37141
37142
37143
37144
37145
37146
37147
37148
37149
37150
37151
37152
37153
37154
37155 );
37156 Vmouse_autoselect_window = Qnil;
37157
37158 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
37159 doc:
37160
37161
37162
37163
37164 );
37165 Vauto_resize_tab_bars = Qt;
37166
37167 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
37168 doc: );
37169 auto_raise_tab_bar_buttons_p = true;
37170
37171 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
37172 doc:
37173
37174
37175
37176
37177 );
37178 Vauto_resize_tool_bars = Qt;
37179
37180 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
37181 doc: );
37182 auto_raise_tool_bar_buttons_p = true;
37183
37184 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
37185 doc:
37186
37187
37188
37189
37190 );
37191 Vmake_cursor_line_fully_visible = Qt;
37192 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
37193
37194 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
37195 doc: );
37196 make_window_start_visible = false;
37197 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
37198 Fmake_variable_buffer_local (Qmake_window_start_visible);
37199
37200 DEFSYM (Qclose_tab, "close-tab");
37201 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
37202 doc:
37203
37204
37205
37206 );
37207 Vtab_bar_border = Qinternal_border_width;
37208
37209 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
37210 doc:
37211
37212
37213
37214 );
37215 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
37216
37217 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
37218 doc: );
37219 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
37220
37221 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
37222 doc:
37223
37224
37225
37226 );
37227 Vtool_bar_border = Qinternal_border_width;
37228
37229 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
37230 doc:
37231
37232
37233
37234 );
37235 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
37236
37237 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
37238 doc: );
37239 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
37240
37241 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
37242 doc:
37243
37244
37245
37246
37247
37248
37249
37250
37251 );
37252 Vtool_bar_style = Qnil;
37253
37254 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
37255 doc:
37256
37257 );
37258 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
37259
37260 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
37261 doc:
37262
37263
37264
37265
37266
37267
37268
37269
37270 );
37271 Vfontification_functions = Qnil;
37272 Fmake_variable_buffer_local (Qfontification_functions);
37273
37274 DEFVAR_BOOL ("unibyte-display-via-language-environment",
37275 unibyte_display_via_language_environment,
37276 doc:
37277
37278
37279
37280
37281
37282
37283 );
37284 unibyte_display_via_language_environment = false;
37285
37286 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
37287 doc:
37288
37289
37290
37291 );
37292 Vmax_mini_window_height = make_float (0.25);
37293
37294 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
37295 doc:
37296
37297
37298
37299
37300
37301
37302
37303
37304 );
37305
37306
37307
37308
37309
37310 Vresize_mini_windows = Qnil;
37311
37312 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
37313 doc:
37314
37315
37316
37317
37318
37319
37320
37321 );
37322 Vblink_cursor_alist = Qnil;
37323
37324 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
37325 doc:
37326
37327
37328
37329 );
37330 automatic_hscrolling = Qt;
37331 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
37332 DEFSYM (Qcurrent_line, "current-line");
37333
37334 DEFVAR_INT ("hscroll-margin", hscroll_margin,
37335 doc:
37336 );
37337 hscroll_margin = 5;
37338
37339 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37340 doc:
37341
37342
37343
37344
37345
37346
37347
37348
37349
37350
37351
37352
37353
37354 );
37355 Vhscroll_step = make_fixnum (0);
37356
37357 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37358 doc:
37359 );
37360 message_truncate_lines = false;
37361
37362 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37363 doc:
37364
37365
37366 );
37367 Vmenu_bar_update_hook = Qnil;
37368
37369 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37370 doc:
37371 );
37372 Vmenu_updating_frame = Qnil;
37373
37374 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37375 doc: );
37376 inhibit_menubar_update = false;
37377
37378 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37379 doc:
37380
37381
37382
37383
37384
37385
37386 );
37387 Vwrap_prefix = Qnil;
37388 DEFSYM (Qwrap_prefix, "wrap-prefix");
37389 Fmake_variable_buffer_local (Qwrap_prefix);
37390
37391 DEFVAR_LISP ("line-prefix", Vline_prefix,
37392 doc:
37393
37394
37395
37396
37397
37398
37399 );
37400 Vline_prefix = Qnil;
37401 DEFSYM (Qline_prefix, "line-prefix");
37402 Fmake_variable_buffer_local (Qline_prefix);
37403
37404 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37405 doc:
37406
37407
37408
37409
37410
37411
37412
37413
37414
37415
37416
37417
37418
37419
37420
37421
37422
37423
37424
37425
37426
37427
37428 );
37429 Vdisplay_line_numbers = Qnil;
37430 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37431 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37432 DEFSYM (Qrelative, "relative");
37433 DEFSYM (Qvisual, "visual");
37434
37435 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37436 doc:
37437
37438
37439
37440 );
37441 Vdisplay_line_numbers_width = Qnil;
37442 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37443 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37444
37445 DEFVAR_LISP ("display-line-numbers-current-absolute",
37446 Vdisplay_line_numbers_current_absolute,
37447 doc:
37448
37449 );
37450 Vdisplay_line_numbers_current_absolute = Qt;
37451
37452 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37453 doc: );
37454 display_line_numbers_widen = false;
37455 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37456 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37457
37458 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37459 doc:
37460
37461
37462 );
37463 display_line_numbers_offset = 0;
37464 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37465 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37466
37467 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37468 doc:
37469
37470
37471 );
37472 display_fill_column_indicator = false;
37473 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37474 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37475
37476 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37477 doc:
37478
37479
37480
37481 );
37482 Vdisplay_fill_column_indicator_column = Qt;
37483 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37484 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37485
37486 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37487 doc:
37488
37489
37490 );
37491 Vdisplay_fill_column_indicator_character = Qnil;
37492 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37493 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37494
37495 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37496 doc:
37497
37498
37499 );
37500 display_line_numbers_major_tick = 0;
37501
37502 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37503 doc:
37504
37505
37506 );
37507 display_line_numbers_minor_tick = 0;
37508
37509 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37510 doc: );
37511 inhibit_eval_during_redisplay = false;
37512
37513 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37514 doc: );
37515 inhibit_free_realized_faces = false;
37516
37517 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37518 doc:
37519
37520 );
37521 inhibit_bidi_mirroring = false;
37522
37523 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37524 doc:
37525
37526
37527
37528 );
37529 bidi_inhibit_bpa = false;
37530
37531 #ifdef GLYPH_DEBUG
37532 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37533 doc: );
37534 inhibit_try_window_id = false;
37535
37536 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37537 doc: );
37538 inhibit_try_window_reusing = false;
37539
37540 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37541 doc: );
37542 inhibit_try_cursor_movement = false;
37543 #endif
37544
37545 DEFVAR_INT ("overline-margin", overline_margin,
37546 doc:
37547
37548 );
37549 overline_margin = 2;
37550
37551 DEFVAR_INT ("underline-minimum-offset",
37552 underline_minimum_offset,
37553 doc:
37554
37555
37556
37557 );
37558 underline_minimum_offset = 1;
37559 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37560
37561 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37562 doc:
37563
37564 );
37565 display_hourglass_p = true;
37566
37567 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37568 doc: );
37569 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37570
37571 #ifdef HAVE_WINDOW_SYSTEM
37572 hourglass_atimer = NULL;
37573 hourglass_shown_p = false;
37574 #endif
37575
37576
37577 DEFSYM (Qglyphless_char, "glyphless-char");
37578
37579
37580 DEFSYM (Qhex_code, "hex-code");
37581 DEFSYM (Qempty_box, "empty-box");
37582 DEFSYM (Qthin_space, "thin-space");
37583 DEFSYM (Qzero_width, "zero-width");
37584
37585 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37586 doc:
37587
37588
37589 );
37590 Vpre_redisplay_function = intern ("ignore");
37591
37592
37593 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37594 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37595
37596 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37597 doc:
37598
37599
37600
37601
37602
37603
37604
37605
37606
37607
37608
37609
37610
37611
37612
37613
37614
37615
37616
37617
37618
37619
37620
37621 );
37622 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37623 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37624 Qempty_box);
37625
37626 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37627 doc: );
37628 Vdebug_on_message = Qnil;
37629
37630 DEFVAR_LISP ("set-message-function", Vset_message_function,
37631 doc:
37632
37633
37634
37635
37636
37637
37638
37639
37640
37641 );
37642 Vset_message_function = Qnil;
37643
37644 DEFSYM (Qdont_clear_message, "dont-clear-message");
37645 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37646 doc:
37647
37648
37649
37650
37651
37652
37653
37654
37655
37656
37657 );
37658 Vclear_message_function = Qnil;
37659
37660 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37661 doc:
37662 );
37663 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37664
37665 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37666 doc:
37667 );
37668 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37669
37670 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37671 doc: );
37672
37673
37674 redisplay__inhibit_bidi = true;
37675
37676 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37677 doc:
37678
37679 );
37680 display_raw_bytes_as_hex = false;
37681
37682 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37683 doc:
37684
37685 );
37686 mouse_fine_grained_tracking = false;
37687
37688 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37689 doc: );
37690 tab_bar__dragging_in_progress = false;
37691
37692 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37693 doc:
37694
37695
37696
37697 );
37698 redisplay_skip_initial_frame = true;
37699
37700 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37701 redisplay_skip_fontification_on_input,
37702 doc:
37703
37704
37705
37706
37707
37708
37709
37710 );
37711 redisplay_skip_fontification_on_input = false;
37712
37713 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37714 redisplay_adhoc_scroll_in_resize_mini_windows,
37715 doc:
37716
37717 );
37718
37719 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37720
37721 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37722 doc:
37723
37724 );
37725 composition_break_at_point = false;
37726
37727 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37728 doc:
37729
37730
37731
37732
37733
37734
37735
37736
37737
37738
37739
37740 );
37741 max_redisplay_ticks = 0;
37742 }
37743
37744
37745
37746
37747 void
37748 init_xdisp (void)
37749 {
37750 CHARPOS (this_line_start_pos) = 0;
37751
37752 echo_area_window = minibuf_window;
37753
37754 if (!noninteractive)
37755 {
37756 struct window *m = XWINDOW (minibuf_window);
37757 Lisp_Object frame = m->frame;
37758 struct frame *f = XFRAME (frame);
37759 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37760 struct window *r = XWINDOW (root);
37761 int i;
37762
37763 r->top_line = FRAME_TOP_MARGIN (f);
37764 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37765 r->total_cols = FRAME_COLS (f);
37766 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37767 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_MARGINS (f);
37768 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37769
37770 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37771 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37772 m->total_cols = FRAME_COLS (f);
37773 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37774 m->total_lines = 1;
37775 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37776
37777 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37778 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37779 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37780
37781
37782 for (i = 0; i < 3; ++i)
37783 default_invis_vector[i] = make_fixnum ('.');
37784 }
37785
37786 {
37787
37788
37789 int size = 100;
37790 mode_line_noprop_buf = xmalloc (size);
37791 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37792 mode_line_noprop_ptr = mode_line_noprop_buf;
37793 mode_line_target = MODE_LINE_DISPLAY;
37794 }
37795
37796 help_echo_showing_p = false;
37797 }
37798
37799 #ifdef HAVE_WINDOW_SYSTEM
37800
37801
37802
37803
37804
37805 static void
37806 show_hourglass (struct atimer *timer)
37807 {
37808
37809
37810
37811 hourglass_atimer = NULL;
37812
37813 if (!hourglass_shown_p)
37814 {
37815 Lisp_Object tail, frame;
37816
37817 block_input ();
37818
37819 FOR_EACH_FRAME (tail, frame)
37820 {
37821 struct frame *f = XFRAME (frame);
37822
37823 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37824 && FRAME_RIF (f)->show_hourglass)
37825 FRAME_RIF (f)->show_hourglass (f);
37826 }
37827
37828 hourglass_shown_p = true;
37829 unblock_input ();
37830 }
37831 }
37832
37833
37834
37835 void
37836 start_hourglass (void)
37837 {
37838 struct timespec delay;
37839
37840 cancel_hourglass ();
37841
37842 if (FIXNUMP (Vhourglass_delay)
37843 && XFIXNUM (Vhourglass_delay) > 0)
37844 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37845 TYPE_MAXIMUM (time_t)),
37846 0);
37847 else if (FLOATP (Vhourglass_delay)
37848 && XFLOAT_DATA (Vhourglass_delay) > 0)
37849 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37850 else
37851 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37852
37853 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37854 show_hourglass, NULL);
37855 }
37856
37857
37858
37859
37860 void
37861 cancel_hourglass (void)
37862 {
37863 if (hourglass_atimer)
37864 {
37865 cancel_atimer (hourglass_atimer);
37866 hourglass_atimer = NULL;
37867 }
37868
37869 if (hourglass_shown_p)
37870 {
37871 Lisp_Object tail, frame;
37872
37873 block_input ();
37874
37875 FOR_EACH_FRAME (tail, frame)
37876 {
37877 struct frame *f = XFRAME (frame);
37878
37879 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37880 && FRAME_RIF (f)->hide_hourglass)
37881 FRAME_RIF (f)->hide_hourglass (f);
37882 #ifdef HAVE_NTGUI
37883
37884 else if (!FRAME_W32_P (f))
37885 w32_arrow_cursor ();
37886 #endif
37887 }
37888
37889 hourglass_shown_p = false;
37890 unblock_input ();
37891 }
37892 }
37893
37894
37895
37896
37897
37898
37899
37900
37901 static int
37902 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37903 struct window *w,
37904 struct face *original_face,
37905 struct face *mouse_face)
37906 {
37907 int sum = 0;
37908
37909 bool do_left_box_p = g->left_box_line_p;
37910 bool do_right_box_p = g->right_box_line_p;
37911
37912
37913
37914 if (g->type == IMAGE_GLYPH)
37915 {
37916 if (!row->reversed_p)
37917 {
37918 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37919 g->u.img_id);
37920 do_left_box_p = g->left_box_line_p &&
37921 g->slice.img.x == 0;
37922 do_right_box_p = g->right_box_line_p &&
37923 g->slice.img.x + g->slice.img.width == img->width;
37924 }
37925 else
37926 {
37927 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37928 g->u.img_id);
37929 do_left_box_p = g->left_box_line_p &&
37930 g->slice.img.x + g->slice.img.width == img->width;
37931 do_right_box_p = g->right_box_line_p &&
37932 g->slice.img.x == 0;
37933 }
37934 }
37935
37936
37937 if (do_left_box_p)
37938 sum -= max (0, original_face->box_vertical_line_width);
37939
37940
37941 if (do_right_box_p)
37942 sum -= max (0, original_face->box_vertical_line_width);
37943
37944 if (g->left_box_line_p)
37945 sum += max (0, mouse_face->box_vertical_line_width);
37946 if (g->right_box_line_p)
37947 sum += max (0, mouse_face->box_vertical_line_width);
37948
37949 return sum;
37950 }
37951
37952
37953
37954
37955
37956
37957
37958
37959
37960 static void
37961 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
37962 int *offset)
37963 {
37964 int sum = 0;
37965
37966 if (row->mode_line_p)
37967 return;
37968
37969 block_input ();
37970
37971 struct frame *f = WINDOW_XFRAME (w);
37972 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
37973 struct glyph *start, *end;
37974 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
37975 int hpos = w->phys_cursor.hpos;
37976 end = &row->glyphs[TEXT_AREA][hpos];
37977
37978 if (!row->reversed_p)
37979 {
37980 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37981 hlinfo->mouse_face_beg_row)
37982 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
37983 else
37984 start = row->glyphs[TEXT_AREA];
37985 }
37986 else
37987 {
37988 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37989 hlinfo->mouse_face_end_row)
37990 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
37991 else
37992 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
37993 }
37994
37995
37996
37997
37998 for ( ; row->reversed_p ? start > end : start < end;
37999 row->reversed_p ? --start : ++start)
38000 sum += adjust_glyph_width_for_mouse_face (start, row, w,
38001 FACE_FROM_ID (f, start->face_id),
38002 mouse_face);
38003
38004 if (row->reversed_p)
38005 sum = -sum;
38006
38007 *offset = sum;
38008
38009 unblock_input ();
38010 }
38011 #endif